From 10ec58f74469869f068d5ab699e088b0657ca838 Mon Sep 17 00:00:00 2001 From: stephan Date: Thu, 15 Jan 2026 08:54:52 +0100 Subject: [PATCH] docs: overhaul repository documentation --- CHANGELOG.md | 2 + README.md | 156 ++++++------------ docs/ARCHITECTURE.md | 59 +++++++ docs/CONFIGURATION.md | 54 ++++++ docs/DEPLOYMENT.md | 68 ++++++++ docs/DEVELOPMENT.md | 44 +++++ docs/FAQ.md | 21 +++ docs/GETTING_STARTED.md | 48 ++++++ docs/TROUBLESHOOTING.md | 37 +++++ docs/USAGE.md | 80 +++++++++ docs/{ => _archive}/admin-token-operations.md | 1 + docs/{ => _archive}/client-quickstart.md | 1 + docs/{ => _archive}/oidc-validation.md | 1 + docs/{ => _archive}/third-party-api.md | 1 + docs/{ => _archive}/update-api.md | 1 + docs/{ => _archive}/update-client.md | 1 + docs/{ => _archive}/update-status.md | 1 + project-management/PROJECT_STATUS.md | 6 + .../requirements/epics/EPIC_000012.md | 42 +++++ .../requirements/stories/US_000040.md | 19 +++ .../requirements/tasks/TASK_000043.md | 20 +++ .../requirements/tasks/TASK_000044.md | 20 +++ 22 files changed, 575 insertions(+), 108 deletions(-) create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/CONFIGURATION.md create mode 100644 docs/DEPLOYMENT.md create mode 100644 docs/DEVELOPMENT.md create mode 100644 docs/FAQ.md create mode 100644 docs/GETTING_STARTED.md create mode 100644 docs/TROUBLESHOOTING.md create mode 100644 docs/USAGE.md rename docs/{ => _archive}/admin-token-operations.md (98%) rename docs/{ => _archive}/client-quickstart.md (96%) rename docs/{ => _archive}/oidc-validation.md (96%) rename docs/{ => _archive}/third-party-api.md (98%) rename docs/{ => _archive}/update-api.md (97%) rename docs/{ => _archive}/update-client.md (97%) rename docs/{ => _archive}/update-status.md (94%) create mode 100644 project-management/requirements/epics/EPIC_000012.md create mode 100644 project-management/requirements/stories/US_000040.md create mode 100644 project-management/requirements/tasks/TASK_000043.md create mode 100644 project-management/requirements/tasks/TASK_000044.md diff --git a/CHANGELOG.md b/CHANGELOG.md index f29ceb7..e75ba48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,8 @@ By: Codex (GPT-5) | 15.01.2026 | โš™๏ธ Code | ID: Makefile-Healthcheck auf Authorization: Bearer angepasst. By: Codex (GPT-5) | | 15.01.2026 | ๐Ÿ—๏ธ Planning | ID: US_000039 und TASK_000042 fuer Doku-Audit angelegt. By: Codex (GPT-5) | | 15.01.2026 | ๐Ÿ“ Req | ID: US_000039 Doku-Audit abgeschlossen (Header-Versionen konsolidiert, Update-Docs korrigiert). By: Codex (GPT-5) | +| 15.01.2026 | ๐Ÿ—๏ธ Planning | ID: EPIC_000012 und US_000040 sowie TASK_000043-TASK_000044 fuer Doku-Overhaul angelegt. By: Codex (GPT-5) | +| 15.01.2026 | ๐Ÿ“ Req | ID: US_000040 Doku-Overhaul umgesetzt (neue Struktur, README, Archivierung). By: Codex (GPT-5) | --- ## Legende diff --git a/README.md b/README.md index f282a02..26df92a 100644 --- a/README.md +++ b/README.md @@ -1,121 +1,61 @@ +ID: README_000001 | Version: 0.2.1 | Status: Draft +By: Codex (GPT-5) + # Safe Kiddo Daemon -Service to lock/unlock local user accounts on kids' laptops with countdown, notifications, optional sound, and shutdown. Provides a REST API plus a small web UI for remote control; retains the original `sk.sh` script as legacy/CLI fallback. +## Kurzbeschreibung +Safe Kiddo Daemon ist ein lokaler Systemdienst, der Benutzerkonten auf Linux-Systemen sperrt/entsperrt, Sitzungen beendet und optional einen Shutdown ausloest. Der Dienst bietet eine REST-API und eine Web-UI fuer die Fernsteuerung. Ein Legacy-CLI-Script (`sk.sh`) bleibt als Fallback erhalten. -## Features -- Disable/enable accounts, terminate sessions, optionally trigger shutdown. -- Desktop notifications and optional sound during countdown. -- Login-protected API with minimal web UI (PAM auth for root users, bearer token for calls). -- Systemd-managed service, virtualenv-based deploy, remote update script. -- Dry-run mode to validate flows without touching accounts. +## Zielgruppe +- Einsteiger: moechten den Dienst schnell installieren und erste Aktionen ausfuehren. +- Admins/Operatoren: konfigurieren Auth, OIDC und Update-Mechanik. +- Entwickler: verstehen Architektur, Module und Erweiterungspunkte. -## Quick Start (Local/Target Device) +## Hauptfunktionen +- Sperren/Entsperren lokaler Nutzerkonten inkl. Session-Management und optionalem Shutdown. +- Benachrichtigungen und optionaler Sound waehrend Countdown. +- PAM-Login (immer aktiv) und optionaler OIDC-Login. +- Systemd-Service mit Installations- und Update-Skripten. +- Update-Client-Integration (Enrollment, Manifest, Apply, Rollback, Logs). +- Dry-Run-Modus zum sicheren Testen. + +## Badges +Derzeit keine offiziellen Badges, da im Repository keine CI, Coverage, Release oder Docker-Pipeline definiert ist. + +## Quickstart (5 Minuten) ```bash -git clone /opt/sk +# 1) Repo holen +sudo mkdir -p /opt/sk +sudo git clone ssh://git@git.wlkns.org:2222/stephan/kiddo /opt/sk +# Hinweis: verwende hier die Repo-URL deiner Instanz cd /opt/sk + +# 2) Installieren (legt User, env und Systemd-Unit an) ./scripts/install.sh + +# 3) Status pruefen sudo systemctl status skd.service + +# 4) Login testen (PAM) +curl -s -X POST -H "Content-Type: application/json" \ + -d '{"username":"root","password":"example-password"}' \ + http://localhost/login ``` -Then open `http://localhost/` and log in via PAM (default) to start quickly. +Danach die Web-UI unter `http://localhost/` oeffnen und anmelden. -## Configuration -Set in `/etc/skd/env` (see `env.example`): -- PAM-Login ist immer aktiv. OIDC wird zusaetzlich angeboten, wenn konfiguriert. -- `SKD_AUTH_SECRET`: HMAC secret for bearer tokens/cookies (set a strong value). -- `SKD_TOKEN_TTL_SECONDS`: token lifetime (default 900s). -- `SKD_AUTH_ALLOWED_USERS`: optional comma list of accounts allowed to log in (used for PAM and as an allowlist for OIDC claims). -- `SKD_AUTH_ALLOWED_GROUPS`: groups whose members may log in (PAM only, default `sudo`). -- `SKD_AUTH_PAM_SERVICE`: PAM service name; Ubuntu/Debian uses `/etc/pam.d/skd` (created by `scripts/install.sh`), other distros may prefer `login` or `sshd`. -- `SKD_OIDC_*`: `ISSUER`, `CLIENT_ID`, `CLIENT_SECRET`, `REDIRECT_URI`, `SCOPES` to point at your OIDC provider; set `SKD_SESSION_COOKIE_SECURE=true` for HTTPS. -- OIDC dynamic registration helper: `scripts/register_oidc_client.sh` (requires `OIDC_INITIAL_ACCESS_TOKEN` and `SKD_OIDC_ISSUER`; uses `SKD_OIDC_REDIRECT_URI` for the redirect). Run once during setup if your provider issues initial access tokens for client creation. -- `SKD_ALLOWED_USERS`: optional comma list to limit manageable accounts (must exist on the system). -- `SKD_DEFAULT_COUNTDOWN`, `SKD_DEFAULT_SOUND`, `SKD_NOTIFY_TIMEOUT`: behavior defaults. -- `SKD_DRY_RUN=true` to test without real account changes or shutdown. -- `SKD_SOUND_PLAYER`/`SKD_SOUND_FILE`, `SKD_NOTIFY_SEND_PATH` if defaults differ. -- Update client: - - `SKD_UPDATE_SERVICE_URL` (default `https://update.wlkns.org`) - - `SKD_UPDATE_PROJECT_ID` (default `safe-kiddo-control`) - - `SKD_UPDATE_ENROLL_TOKEN` (one-time enrollment token for `/update/enroll`) - - `SKD_UPDATE_TOKEN` (API token for update service; or load from `SKD_UPDATE_TOKEN_FILE`) - - `SKD_UPDATE_TOKEN_FILE` (default `/var/lib/skd/update_token`) - - `SKD_UPDATE_INTERVAL` (seconds; default 3600) - - `SKD_UPDATE_STATUS_FILE` (default `/var/lib/skd/update_status.json`) - - `SKD_UPDATE_LOG_FILE` (default `/var/lib/skd/update_logs.jsonl`) -Notes: -- `./scripts/install.sh` will create `/etc/skd/env` from `env.example` if missing (edit afterwards) and ensure the `skd` service user/group exist. +## Dokumentation +- Einstieg und erster Lauf: `docs/GETTING_STARTED.md` +- Nutzung (API, Web-UI, CLI): `docs/USAGE.md` +- Konfiguration (ENV-Variablen): `docs/CONFIGURATION.md` +- Architektur und Module: `docs/ARCHITECTURE.md` +- Entwicklung: `docs/DEVELOPMENT.md` +- Deployment & Betrieb: `docs/DEPLOYMENT.md` +- FAQ: `docs/FAQ.md` +- Troubleshooting: `docs/TROUBLESHOOTING.md` -## OIDC Setup -OIDC ist optional. PAM bleibt immer verfuegbar; `SKD_AUTH_MODE` ist optional. -1. Issuer muss der externen URL des Providers entsprechen (TLS trust erforderlich). -2. OIDC Client registrieren (DCR), z.B.: -```bash -export SKD_OIDC_ISSUER="https://auth.example.org" -export SKD_OIDC_REDIRECT_URI="https:///login/oidc/callback" -export OIDC_INITIAL_ACCESS_TOKEN="" -./scripts/register_oidc_client.sh -``` -3. Danach in `/etc/skd/env` setzen: -``` -SKD_AUTH_MODE=oidc -SKD_OIDC_ISSUER=... -SKD_OIDC_CLIENT_ID=... -SKD_OIDC_CLIENT_SECRET=... -SKD_OIDC_REDIRECT_URI=... -SKD_OIDC_SCOPES=openid profile email -SKD_SESSION_COOKIE_SECURE=true -``` -Hinweise: -- Redirect-URI muss exakt sein (keine Wildcards). -- Bei Host/Port-Aenderung neu registrieren und neue Credentials setzen. -- Allowlist fuer OIDC: `SKD_AUTH_ALLOWED_USERS` prueft `preferred_username`, `email` oder `sub`. - -## Running -- Service: managed by systemd; `./scripts/install.sh` writes the unit dynamically to `/etc/systemd/system/skd.service` with the current repo path and restarts it (runs as root for PAM). -- Manual run: `./scripts/run.sh` (uses `.venv`, defaults to `0.0.0.0:80`). -- Login (PAM): `curl -X POST -H "Content-Type: application/json" -d '{"username":"root","password":"..."}' http://localhost/login` -- Login (OIDC): open `http://localhost/login/oidc/start` โ†’ provider โ†’ redirected back with session cookie set. -- Health: `curl -H "Authorization: Bearer " http://localhost/health` - -## OIDC Validation & Fallbacks -- Validierungsschritte: `docs/oidc-validation.md` (State, Token-Exchange, Claims, Cookie). -- Falls Discovery/JWKS nicht verfuegbar: OIDC deaktivieren und PAM nutzen. -- Falls DCR nicht verfuegbar: Client manuell im IdP anlegen und `SKD_OIDC_*` setzen. -- Bei Self-Signed TLS: CA im System trusten oder in Dev PAM nutzen. - -## API (Bearer token via `/login`) -- `GET /users` โ†’ `[{user, logged_in, account_locked}]` (manageable system users; excludes root) -- `POST /users/{name}/disable` with JSON `{countdown?, sound?, message?}` -- `POST /users/{name}/enable` -- `GET /health` -- `GET /me` (returns current user + auth mode when a session/bearer token is present) - -Example: -```bash -token=$(curl -s -X POST -H "Content-Type: application/json" -d '{"username":"root","password":"..."}' http://localhost/login | jq -r .token) -curl -X POST -H "Authorization: Bearer $token" \ - -H "Content-Type: application/json" \ - -d '{"countdown":90,"sound":true}' \ - http://localhost/users/child1/disable -``` - -## Web UI -Served at `/`. Nutze den Button โ€žLogin via OIDCโ€œ (setzt Session-Cookie) oder das PAM-Formular, falls OIDC deaktiviert; danach werden verfรผgbare System-User angezeigt und Aktionen senden Token/Cookies automatisch. - -## Updates -- Remote update via SSH: `ssh user@kid-laptop 'cd /opt/sk && ./scripts/update.sh'` (fetch/reset to `origin/main`, reinstalls deps, restarts service). -- Manual: `git pull && source .venv/bin/activate && pip install -r backend/requirements.txt && sudo systemctl restart skd` - -## Deployment (zip/SSH) -- Quick copy: create `sk_deploy.zip` (already in repo root) and unzip on target under `/opt/sk`, then refresh venv deps and restart service. -- Scripted deploy: edit `deploy_hosts.yml` (host/user/port/install_dir/service user/group), then run `./scripts/deploy.sh `; accepts JSON configs too. Requires SSH access and `sudo` on target. -- After deploy on target: `sudo -u skd /opt/sk/.venv/bin/pip install -r /opt/sk/backend/requirements.txt && sudo systemctl restart skd.service` - -## Security Hardening -- Restrict access to API/Web UI to LAN/VPN; firewall the port. -- Set a strong `SKD_AUTH_SECRET`; rotate tokens by changing the secret. -- Create dedicated `skd` user/group; no login shell. -- Configure sudoers minimally: allow `skd` to run `usermod -L/-U`, `pkill -KILL -u`, `shutdown now`, and sound/notify binaries if needed (no full passwordless sudo). -- Consider mTLS or IP allowlisting for added protection. +## Hinweise +- Abweichung von der Zielstruktur: Die OpenAPI-Spezifikation des Update-Services bleibt unter `docs/architecture/openapi.yaml` und `docs/architecture/openapi/` erhalten. +- Altdokumente liegen unter `docs/_archive/` und sind nicht geloescht. ## Legacy Script -`sk.sh` remains for direct SSH use. Plan to replace its logic with API-backed helpers; keep it as emergency fallback. +Das Script `sk.sh` bleibt als CLI-Fallback. Details und Beispiele: `docs/USAGE.md`. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..0ea974f --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,59 @@ +ID: DOC_000012 | Version: 0.2.1 | Status: Draft +By: Codex (GPT-5) + +# Architektur + +## Systemuebersicht +Safe Kiddo Daemon ist ein FastAPI-basierter Service, der lokale Systemkonten verwaltet. Er kombiniert: +- API und Web-UI (FastAPI + Jinja2 Templates) +- Authentifizierung (PAM und optional OIDC) +- Systemaktionen via sudo/usermod/pkill/shutdown +- Update-Client-Integration (externes Update-Service-Backend) + +## Module und Verantwortlichkeiten +- `backend/app.py`: API-Routing, Web-UI-Endpunkte, Update-Endpunkte. +- `backend/auth.py`: PAM-Login, JWT-Handling, Auth-Guards, Allowlists. +- `backend/oidc.py`: OIDC Discovery, Token-Exchange, JWT-Validierung. +- `backend/actions.py`: Systemaktionen (lock/unlock, notify, sound, shutdown). +- `backend/update.py`: Update-Enrollment, Manifest-Check, Update/Rollback-Start, Status/Logs. +- `backend/settings.py`: Zentrale ENV-Konfiguration. +- `backend/templates/` + `backend/static/`: Web-UI. +- `scripts/*.sh`: Installation, Deployment, Update-Client, Rollback, OIDC-Registration. + +## Daten- und Kontrollfluss +### Login und Auth +1. `POST /login` authentifiziert via PAM. +2. JWT wird erstellt und als Cookie oder Bearer-Token genutzt. +3. Schutz aller Admin-Endpunkte via `get_current_admin`. + +### OIDC-Flow (optional) +1. `GET /login/oidc/start` generiert State und leitet zum IdP. +2. Callback `GET /login/oidc/callback` validiert State, tauscht Code gegen ID-Token. +3. ID-Token wird gegen JWKS geprueft, Username extrahiert, Session gesetzt. + +### Benutzeraktionen +1. `POST /users/{username}/disable` ruft `actions.disable_user`. +2. Systemaktionen: `usermod -L`, optional notify/sound, `pkill`, optional `shutdown`. +3. `POST /users/{username}/enable` fuehrt `usermod -U` aus. + +### Update-Flow +1. `POST /update/enroll` schreibt Langzeit-Token in `SKD_UPDATE_TOKEN_FILE`. +2. `POST /update/check` ruft Manifest beim Update-Service ab. +3. `POST /update/apply` startet `scripts/update_client.sh` asynchron. +4. `POST /update/rollback` startet `scripts/rollback_client.sh` asynchron. +5. Status/Logs werden lokal in Dateien geschrieben und optional an den Update-Service gemeldet. + +## Designentscheidungen und Tradeoffs +- **Root-Run**: Service laeuft als root, da PAM und Systemkommandos Root erfordern. +- **JWT + Cookie**: Einfache lokale Auth; keine externe Session-Datenbank. +- **OIDC optional**: OIDC ist optional, PAM bleibt als Fallback aktiv. +- **Update als Script**: Update/Backup/Swap via Bash-Skripte fuer einfache Ops, Tradeoff: weniger granularer Fehler-Handling. + +## Erweiterungspunkte +- **Auth**: Weitere Auth-Mechanismen koennen in `backend/auth.py` integriert werden. +- **UI**: Templates unter `backend/templates/` und CSS in `backend/static/`. +- **Update-Client**: Anpassung der Update-Strategie in `scripts/update_client.sh`. +- **Notifications/Sound**: Konfigurierbar per `SKD_NOTIFY_SEND_PATH`, `SKD_SOUND_PLAYER`, `SKD_SOUND_FILE`. + +## Spezifikationen +- Update-Service OpenAPI: `docs/architecture/openapi.yaml` und `docs/architecture/openapi/`. diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md new file mode 100644 index 0000000..e6b17ab --- /dev/null +++ b/docs/CONFIGURATION.md @@ -0,0 +1,54 @@ +ID: DOC_000011 | Version: 0.2.1 | Status: Draft +By: Codex (GPT-5) + +# Konfiguration + +## Speicherort +Die Konfiguration erfolgt per ENV-Datei, standardmaessig `/etc/skd/env`. Vorlage: `env.example`. + +## Authentifizierung +- `SKD_AUTH_MODE` (default `pam`): `pam` oder `oidc`. Ungueltige Werte fallen auf `pam` zurueck. Hinweis: Der Wert wird aktuell nicht zur Erzwingung genutzt; OIDC ist aktiv, sobald die OIDC-Variablen gesetzt sind. +- `SKD_AUTH_SECRET` (default `change-me-secret`): HMAC-Secret fuer JWTs. +- `SKD_TOKEN_TTL_SECONDS` (default `900`): Token-Laufzeit in Sekunden. +- `SKD_AUTH_ALLOWED_USERS` (default leer): Kommagetrennte Liste erlaubter Admin-User (gilt fuer PAM und OIDC). +- `SKD_AUTH_ALLOWED_GROUPS` (default `sudo`): Erlaubte Gruppen fuer PAM-Login. +- `SKD_AUTH_PAM_SERVICE` (default `login`, auf Debian/Ubuntu via `install.sh` auf `skd` gesetzt). + +## OIDC +OIDC ist optional und zusaetzlich zu PAM. +- `SKD_OIDC_ISSUER` +- `SKD_OIDC_CLIENT_ID` +- `SKD_OIDC_CLIENT_SECRET` +- `SKD_OIDC_REDIRECT_URI` (default `http://localhost:8000/login/oidc/callback`) +- `SKD_OIDC_SCOPES` (default `openid profile email`) +- `SKD_SESSION_COOKIE_SECURE` (default `false`): Setze `true` fuer HTTPS. +- `SKD_OIDC_STATE_COOKIE_NAME` (default `skd_oidc_state`) + +## Session/Benutzerverwaltung +- `SKD_SESSION_COOKIE_NAME` (default `skd_session`) +- `SKD_ALLOWED_USERS` (default leer): Optionales Allowlist fuer verwaltbare System-User. + +## Aktionen (Countdown/Notify/Sound) +- `SKD_DEFAULT_COUNTDOWN` (default `60` Sekunden) +- `SKD_DEFAULT_SOUND` (default `false`) +- `SKD_NOTIFY_TIMEOUT` (default `5` Sekunden) +- `SKD_NOTIFY_SEND_PATH` (default `notify-send`) +- `SKD_SOUND_PLAYER` (default `paplay`) +- `SKD_SOUND_FILE` (default `/usr/share/sounds/freedesktop/stereo/dialog-warning.oga`) + +## Update-Client +- `SKD_UPDATE_SERVICE_URL` (default `https://update.wlkns.org`) +- `SKD_UPDATE_PROJECT_ID` (default `safe-kiddo-control`) +- `SKD_UPDATE_ENROLL_TOKEN` (optional; fuer `/update/enroll`) +- `SKD_UPDATE_TOKEN` (optional; alternativ per Datei) +- `SKD_UPDATE_TOKEN_FILE` (default `/var/lib/skd/update_token`) +- `SKD_UPDATE_STATUS_FILE` (default `/var/lib/skd/update_status.json`) +- `SKD_UPDATE_LOG_FILE` (default `/var/lib/skd/update_logs.jsonl`) +- `SKD_UPDATE_INTERVAL` (default `3600`): Hinweis: wird aktuell nur eingelesen, aber nicht automatisch genutzt. + +## Dry-Run +- `SKD_DRY_RUN` (default `false`): Keine echten System-Aktionen, nur Logging. + +## Hinweise +- `scripts/install.sh` erstellt `/etc/skd/env` und setzt Default-Werte fuer PAM/Allowed-User. +- Aenderungen in `/etc/skd/env` erfordern einen Service-Restart (`sudo systemctl restart skd.service`). diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md new file mode 100644 index 0000000..c2d189b --- /dev/null +++ b/docs/DEPLOYMENT.md @@ -0,0 +1,68 @@ +ID: DOC_000014 | Version: 0.2.1 | Status: Draft +By: Codex (GPT-5) + +# Deployment + +## Lokale Installation (systemd) +`./scripts/install.sh` fuehrt folgende Schritte aus: +- legt Service-User/Group an +- kopiert das Projekt nach `/opt/sk` +- erstellt/aktualisiert `.venv` +- erstellt `/etc/skd/env` aus `env.example` +- schreibt eine systemd-Unit nach `/etc/systemd/system/skd.service` + +Beispiel: +```bash +sudo ./scripts/install.sh +sudo systemctl status skd.service +``` + +## Manuelles Starten +```bash +./scripts/run.sh +``` + +## Remote-Deploy (SSH) +`./scripts/deploy.sh` packt das Repo und deployt es auf einen Zielhost. +Konfiguration in `deploy_hosts.yml`. + +Beispiel: +```bash +./scripts/deploy.sh kid-laptop +``` + +## Deployment via ZIP +Im Repo liegt `sk_deploy.zip`. Dieses Archiv kann auf den Zielhost kopiert und nach `/opt/sk` entpackt werden. +Anschliessend Abhaengigkeiten installieren und Service neu starten: +```bash +sudo -u skd /opt/sk/.venv/bin/pip install -r /opt/sk/backend/requirements.txt +sudo systemctl restart skd.service +``` +## Update des Services +`./scripts/update.sh` zieht den Branch neu und fuehrt einen harten Reset aus. + +Wichtig: Das Script nutzt `git reset --hard origin/main`. +```bash +sudo ./scripts/update.sh +``` + +## Update-Client (Remote Update Service) +Die Update-API startet `scripts/update_client.sh` bzw. `scripts/rollback_client.sh`. +Wichtige ENV-Variablen: +- `SKD_UPDATE_SERVICE_URL` +- `SKD_UPDATE_PROJECT_ID` +- `SKD_UPDATE_TOKEN` oder `SKD_UPDATE_TOKEN_FILE` +Voraussetzungen auf dem Host: +- `curl`, `tar`, `sha256sum`, `python3`, `systemctl` + +Enrollment-Tools: +- `scripts/manual_enroll.py`: Enrollment direkt gegen den Update-Service, schreibt Token in `SKD_UPDATE_TOKEN_FILE`. +- `scripts/enroll_local.py`: Enrollment ueber die lokale API (`/update/enroll`), benoetigt Admin-Session; `--token` setzen (Default-Token ist nur Prototyp-Altlast). + +Lokale Status/Logs: +- `SKD_UPDATE_STATUS_FILE` (default `/var/lib/skd/update_status.json`) +- `SKD_UPDATE_LOG_FILE` (default `/var/lib/skd/update_logs.jsonl`) + +## Backup/Restore +- Bei Apply wird `/opt/sk` nach `/opt/sk_backup_1.2.3_1700000000` verschoben (Beispiel). +- Rollback nutzt das letzte Backup (`/opt/sk_backup_*`). diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 0000000..e5f2792 --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -0,0 +1,44 @@ +ID: DOC_000013 | Version: 0.2.1 | Status: Draft +By: Codex (GPT-5) + +# Development + +## Repository-Struktur (Kurz) +- `backend/`: FastAPI-App, Auth, Update-Logik, Templates, Static Assets. +- `scripts/`: Install/Deploy/Update/Helper-Skripte. +- `systemd/`: Beispiel-Unit. +- `docs/architecture/`: OpenAPI-Spezifikation fuer Update-Service. +- `docs/`: Dokumentation. +- `assets/`: Branding und Design. +- `sk.sh`: Legacy-CLI. + +## Lokales Setup +```bash +./scripts/create_venv.sh +source .venv/bin/activate +./scripts/run.sh +``` +Standard: `0.0.0.0:80`. Fuer andere Ports: +```bash +HOST=127.0.0.1 PORT=8000 ./scripts/run.sh +``` + +## Tests und Lint +Im Repo sind keine automatisierten Tests enthalten. Verfuegbare Checks: +- Bash-Syntax: `bash -n sk.sh` +- ShellCheck: `shellcheck sk.sh` + +## Coding Conventions +- Bash 4+, `set -euo pipefail` in neuen Skripten. +- Python: FastAPI-Patterns, klare Modultrennung (Auth, Actions, Update, OIDC). + +## Beitrag und Workflow +- Arbeite mit Feature-Branches. +- Aktualisiere `VERSION`, Doku-Header und `CHANGELOG.md` gemaess SOP. +- PRs sollten Verhalten, Risiken und manuelle Tests beschreiben. + +## CI/CD +Aktuell keine CI/CD-Pipeline im Repository definiert. + +## Legacy/Interna +- `SKD_UPDATE_URL` und `SKD_UPDATE_STATUS_URL` sind in `backend/settings.py` noch vorhanden, werden aber im aktuellen Code nicht genutzt. diff --git a/docs/FAQ.md b/docs/FAQ.md new file mode 100644 index 0000000..38aa5dc --- /dev/null +++ b/docs/FAQ.md @@ -0,0 +1,21 @@ +ID: DOC_000015 | Version: 0.2.1 | Status: Draft +By: Codex (GPT-5) + +# FAQ + +## Braucht der Dienst Root-Rechte? +Ja. PAM-Authentifizierung und Systemkommandos (usermod/pkill/shutdown) erfordern Root. + +## Kann ich OIDC ohne PAM nutzen? +OIDC ist optional und zusaetzlich zu PAM. PAM bleibt als Fallback aktiv. + +## Wie aendere ich den Port? +- Lokaler Run: `PORT=8000 ./scripts/run.sh` +- Systemd: Unit-Datei in `/etc/systemd/system/skd.service` anpassen und Service neu starten. + +## Gibt es einen Docker-Container? +Nein, im Repository ist kein Docker-Setup enthalten. + +## Wo liegen Logs? +- systemd: `journalctl -u skd.service` +- Update-Status/Logs: siehe `SKD_UPDATE_STATUS_FILE` und `SKD_UPDATE_LOG_FILE`. diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md new file mode 100644 index 0000000..1b25697 --- /dev/null +++ b/docs/GETTING_STARTED.md @@ -0,0 +1,48 @@ +ID: DOC_000009 | Version: 0.2.1 | Status: Draft +By: Codex (GPT-5) + +# Getting Started + +## Ziel +Schneller Einstieg fuer neue Nutzer: Installation, erster Login und erste Aktion. + +## Voraussetzungen +- Linux-System mit systemd. +- Root-Zugriff (PAM, usermod, shutdown). +- Python 3, curl, tar, sha256sum (fuer Update-Client-Skripte). +- Optional: notify-send (Benachrichtigungen), paplay/aplay (Sound). + +## Schnellstart +```bash +# 1) Repo installieren +sudo mkdir -p /opt/sk +sudo git clone ssh://git@git.wlkns.org:2222/stephan/kiddo /opt/sk +# Hinweis: verwende hier die Repo-URL deiner Instanz +cd /opt/sk + +# 2) Installation (legt Service-User, env, systemd-Unit an) +./scripts/install.sh + +# 3) Service pruefen +sudo systemctl status skd.service + +# 4) Login (PAM) +curl -s -X POST -H "Content-Type: application/json" \ + -d '{"username":"root","password":"..."}' \ + http://localhost/login +``` + +## Erster API-Test +```bash +token=$(curl -s -X POST -H "Content-Type: application/json" \ + -d '{"username":"root","password":"example-password"}' \ + http://localhost/login | jq -r .token) + +curl -s -H "Authorization: Bearer $token" http://localhost/me +``` +Hinweis: `jq` ist optional; ohne jq das Token manuell aus der JSON-Antwort lesen. + +## Naechste Schritte +- Konfiguration anpassen: `docs/CONFIGURATION.md` +- API und Web-UI nutzen: `docs/USAGE.md` +- Deployment und Updates: `docs/DEPLOYMENT.md` diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md new file mode 100644 index 0000000..55dbd2f --- /dev/null +++ b/docs/TROUBLESHOOTING.md @@ -0,0 +1,37 @@ +ID: DOC_000016 | Version: 0.2.1 | Status: Draft +By: Codex (GPT-5) + +# Troubleshooting + +## Service startet nicht +- Status pruefen: `sudo systemctl status skd.service` +- Logs: `sudo journalctl -u skd.service -n 200 --no-pager` +- Port 80 belegt? Test: `sudo ss -ltnp | grep ':80'` + +## 401/403 bei API-Aufrufen +- Bearer-Token fehlt oder abgelaufen. +- Nutzer nicht in `SKD_AUTH_ALLOWED_USERS` oder `SKD_AUTH_ALLOWED_GROUPS`. +- `SKD_AUTH_SECRET` geaendert? Tokens muessen neu erzeugt werden. + +## OIDC-Login fehlschlaegt +- `SKD_OIDC_ISSUER`, `SKD_OIDC_CLIENT_ID`, `SKD_OIDC_CLIENT_SECRET` gesetzt? +- Redirect-URI exakt registriert? +- Netzwerkzugriff auf Discovery/JWKS moeglich? + +## Benachrichtigung/Sound fehlt +- `notify-send` fehlt: `sudo apt install libnotify-bin` +- Sound-Player fehlt: `paplay` oder `aplay` installieren. +- `SKD_NOTIFY_SEND_PATH` oder `SKD_SOUND_PLAYER` falsch gesetzt. + +## Update-Check meldet "Client is not enrolled" +- `SKD_UPDATE_TOKEN` oder `SKD_UPDATE_TOKEN_FILE` fehlt. +- Enrollment ueber `/update/enroll` oder `scripts/manual_enroll.py` durchfuehren. + +## Update-Apply fehlschlaegt +- Update-Service nicht erreichbar oder Token ungueltig. +- Prรผfe `SKD_UPDATE_STATUS_FILE` und `SKD_UPDATE_LOG_FILE`. +- Hinweis: `update_client.sh` wird asynchron gestartet und stdout/stderr werden verworfen. + +## Rollback meldet "no backup found" +- Es existiert kein `/opt/sk_backup_*` vom vorherigen Update. +- Rollback erst nach mindestens einem erfolgreichen Update moeglich. diff --git a/docs/USAGE.md b/docs/USAGE.md new file mode 100644 index 0000000..706c2df --- /dev/null +++ b/docs/USAGE.md @@ -0,0 +1,80 @@ +ID: DOC_000010 | Version: 0.2.1 | Status: Draft +By: Codex (GPT-5) + +# Usage + +## Authentifizierung +- PAM-Login: `POST /login` mit Benutzername/Passwort. Liefert JWT und setzt Session-Cookie. +- OIDC-Login: `GET /login/oidc/start` startet Flow, Callback setzt Session-Cookie. +- Alle geschuetzten Endpunkte akzeptieren `Authorization: Bearer $TOKEN` oder Session-Cookie. + +### Beispiel: Login und Token nutzen +```bash +token=$(curl -s -X POST -H "Content-Type: application/json" \ + -d '{"username":"root","password":"example-password"}' \ + http://localhost/login | jq -r .token) + +curl -s -H "Authorization: Bearer $token" http://localhost/me +``` +Hinweis: `jq` ist optional; ohne jq das Token manuell aus der JSON-Antwort lesen. +Login ist nur fuer erlaubte Nutzer moeglich (siehe `SKD_AUTH_ALLOWED_USERS` und `SKD_AUTH_ALLOWED_GROUPS`). + +## Web-UI +- Aufruf: `http://localhost/` +- Login per PAM oder OIDC (wenn konfiguriert). +- Aktionen: Benutzer sperren/entsperren, Update-Status, Update-Check, Apply/Rollback. + +## API-Endpunkte (Auszug) +### Health und Identitaet +- `GET /health` (ohne Auth) +- `GET /me` + +### Benutzerverwaltung +- `GET /users` +- `POST /users/{username}/disable` mit JSON `{countdown?, sound?, message?}` +- `POST /users/{username}/enable` + +Beispiel (disable): +```bash +curl -X POST -H "Authorization: Bearer $token" \ + -H "Content-Type: application/json" \ + -d '{"countdown":90,"sound":true,"message":"Bitte speichern"}' \ + http://localhost/users/child1/disable +``` + +### Update-API (lokal) +Alle Update-Endpunkte erfordern Admin-Auth. +- `GET /update/status` +- `POST /update/enroll` (optional Body: `{ "enroll_token": "..." }`) +- `POST /update/check` +- `POST /update/apply` (optional Body: `{ "version": "x.y.z" }`) +- `POST /update/rollback` +- `GET /update/logs?limit=200` + +Beispiel (Enrollment): +```bash +ENROLL_TOKEN="example-enroll-token" +curl -X POST -H "Authorization: Bearer $token" \ + -H "Content-Type: application/json" \ + -d "{\"enroll_token\":\"${ENROLL_TOKEN}\"}" \ + http://localhost/update/enroll +``` + +Beispiel (Update-Check): +```bash +curl -X POST -H "Authorization: Bearer $token" http://localhost/update/check +``` +Hinweis: Ohne gespeichertes Update-Token liefert der Check einen Fehler. + +## CLI-Fallback (sk.sh) +Das Legacy-Script arbeitet direkt auf dem Host und benoetigt Root-Rechte. + +Aufruf: +```bash +sudo ./sk.sh USERNAME disable|enable [countdown] [sound] [countdown_time_in_seconds] +``` + +Beispiel: +```bash +sudo ./sk.sh demo_user disable countdown sound 90 +``` diff --git a/docs/admin-token-operations.md b/docs/_archive/admin-token-operations.md similarity index 98% rename from docs/admin-token-operations.md rename to docs/_archive/admin-token-operations.md index 31e6e25..60a1b5e 100644 --- a/docs/admin-token-operations.md +++ b/docs/_archive/admin-token-operations.md @@ -1,4 +1,5 @@ ID: DOC_000006 | Version: 0.2.1 | Status: Draft +Archived โ€“ superseded by new documentation. By: Codex (GPT-5) # Admin Token Operations diff --git a/docs/client-quickstart.md b/docs/_archive/client-quickstart.md similarity index 96% rename from docs/client-quickstart.md rename to docs/_archive/client-quickstart.md index 6ce3b5a..534c013 100644 --- a/docs/client-quickstart.md +++ b/docs/_archive/client-quickstart.md @@ -1,4 +1,5 @@ ID: DOC_000008 | Version: 0.2.1 | Status: Draft +Archived โ€“ superseded by new documentation. # Client Quickstart diff --git a/docs/oidc-validation.md b/docs/_archive/oidc-validation.md similarity index 96% rename from docs/oidc-validation.md rename to docs/_archive/oidc-validation.md index b4678ad..3ffbd13 100644 --- a/docs/oidc-validation.md +++ b/docs/_archive/oidc-validation.md @@ -1,4 +1,5 @@ ID: DOC_000003 | Version: 0.2.1 | Status: Draft +Archived โ€“ superseded by new documentation. By: Codex (GPT-5) # OIDC End-to-End Validation (Kiddo) diff --git a/docs/third-party-api.md b/docs/_archive/third-party-api.md similarity index 98% rename from docs/third-party-api.md rename to docs/_archive/third-party-api.md index a151dad..19bca3c 100644 --- a/docs/third-party-api.md +++ b/docs/_archive/third-party-api.md @@ -1,4 +1,5 @@ ID: DOC_000005 | Version: 0.2.1 | Status: Draft +Archived โ€“ superseded by new documentation. By: Codex (GPT-5) # Third-Party API Guide diff --git a/docs/update-api.md b/docs/_archive/update-api.md similarity index 97% rename from docs/update-api.md rename to docs/_archive/update-api.md index d5533a3..ff642b6 100644 --- a/docs/update-api.md +++ b/docs/_archive/update-api.md @@ -1,4 +1,5 @@ ID: DOC_000006 | Version: 0.2.1 | Status: Draft +Archived โ€“ superseded by new documentation. By: Codex (GPT-5) # Update API (Kiddo Backend) diff --git a/docs/update-client.md b/docs/_archive/update-client.md similarity index 97% rename from docs/update-client.md rename to docs/_archive/update-client.md index 51d1c43..73ebbd4 100644 --- a/docs/update-client.md +++ b/docs/_archive/update-client.md @@ -1,4 +1,5 @@ ID: DOC_000004 | Version: 0.2.1 | Status: Draft +Archived โ€“ superseded by new documentation. By: Codex (GPT-5) # Client Update Flow (Kiddo) diff --git a/docs/update-status.md b/docs/_archive/update-status.md similarity index 94% rename from docs/update-status.md rename to docs/_archive/update-status.md index 6dabcef..b96fab7 100644 --- a/docs/update-status.md +++ b/docs/_archive/update-status.md @@ -1,4 +1,5 @@ ID: DOC_000005 | Version: 0.2.1 | Status: Draft +Archived โ€“ superseded by new documentation. By: Codex (GPT-5) # Update Status Reporting diff --git a/project-management/PROJECT_STATUS.md b/project-management/PROJECT_STATUS.md index 0214743..30ee44f 100644 --- a/project-management/PROJECT_STATUS.md +++ b/project-management/PROJECT_STATUS.md @@ -19,6 +19,7 @@ Sicheres, remote steuerbares System zum Sperren/Entsperren lokaler Nutzerkonten. |---|---|---| | 28.12.2025 | ๐Ÿ—๏ธ Planning | Anforderungen als Epics und Stories dokumentiert. | | 15.01.2026 | ๐Ÿ“ Req | Doku und ENV-Beispiele an Code-Stand angepasst. | +| 15.01.2026 | ๐Ÿ“ Req | Doku-Overhaul mit neuer Struktur und Archivierung. | ## Epic-Backlog (Uebersicht) ### EPIC_000001: Legacy CLI Account Control (sk.sh) @@ -122,6 +123,11 @@ Sicheres, remote steuerbares System zum Sperren/Entsperren lokaler Nutzerkonten. - [x] US_000039: Doku-Audit fuer verbleibende Abweichungen - [x] TASK_000042: Doku-Audit verbleibender Dateien +### EPIC_000012: Dokumentations-Overhaul +- [x] US_000040: Doku-Struktur und Inhalte erstellen +- [x] TASK_000043: Neue Doku-Dateien erstellen und verlinken +- [x] TASK_000044: Altdoku archivieren + ## Offene Risiken / Abhaengigkeiten - Betrieb erfordert Root/sudo und lokale System-Tools (notify-send, sound player, uvicorn). - OIDC-Validierung blockiert bis IdP bereit und Service laeuft. diff --git a/project-management/requirements/epics/EPIC_000012.md b/project-management/requirements/epics/EPIC_000012.md new file mode 100644 index 0000000..5566aa9 --- /dev/null +++ b/project-management/requirements/epics/EPIC_000012.md @@ -0,0 +1,42 @@ +ID: EPIC_000012 | Version: 0.2.1 | Status: Done +By: Codex (GPT-5) + +# EPIC_000012: Dokumentations-Overhaul + +## Beschreibung +Komplette, konsistente Dokumentation fuer Einsteiger, Admins und Entwickler, inkl. Archivierung +veralteter Inhalte und einer klaren Doku-Struktur. + +## Ziel / Business Value +Schnelleres Onboarding, weniger Fehlkonfigurationen und klare Betriebsvorgaenge. + +## Mission Statement +Stelle eine professionelle, konsistente und vollstaendige Doku bereit, die sich direkt am +Code und den Skripten orientiert. + +## Business Value & Metriken +- Onboarding ohne Rueckfragen fuer neue Entwickler. +- Betriebssicherheit durch klare Runbooks. +- Erfolgsmetrik: 0 offene Doku-Abweichungen im Audit. + +## In-Scope (Kiddo Team) +- Neue Doku-Struktur und konsistente Inhalte. +- README auf Einsteigerpfad + Links auf neue Dokus. +- Altdokumente archivieren, nicht loeschen. + +## Out-of-Scope +- Funktionale Code-Aenderungen (nur Doku). +- Neue Automatisierungen/CI-Pipelines. + +## High-Level Akzeptanzkriterien +- README erfuellt definierte Anforderungen. +- Doku-Struktur gem. Ziel (GETTING_STARTED/USAGE/CONFIGURATION/ARCHITECTURE/DEVELOPMENT/DEPLOYMENT/FAQ/TROUBLESHOOTING). +- Altdoku in docs/_archive/ mit Archiv-Header. +- Interne Links funktionieren und keine inhaltlichen Widersprueche. + +## Technische Constraints & Risiken +- Keine spekulativen Inhalte; nur dokumentieren, was im Repo belegt ist. +- Sprachvorgabe: Deutsch, ASCII wo moeglich. + +## Zugeordnete User Stories +- US_000040: Doku-Struktur und Inhalte erstellen diff --git a/project-management/requirements/stories/US_000040.md b/project-management/requirements/stories/US_000040.md new file mode 100644 index 0000000..96311c4 --- /dev/null +++ b/project-management/requirements/stories/US_000040.md @@ -0,0 +1,19 @@ +ID: US_000040 | Version: 0.2.1 | Status: Done +By: Codex (GPT-5) + +# US_000040: Doku-Struktur und Inhalte erstellen + +Als Nutzer moechte ich eine klare, vollstaendige Dokumentation, damit Einsteiger, +Admins und Entwickler das System ohne Rueckfragen verstehen und betreiben koennen. + +## Akzeptanzkriterien +- Given die Zielstruktur ist definiert +- When die Dokumentation erstellt wird +- Then existieren alle Ziel-Dokumente mit korrekten Inhalten +- And README enthaelt Quickstart, Zielgruppen, Features und Links +- And alle Inhalte basieren auf Code/Skripten ohne Spekulation +- And Altdokumente sind archiviert statt geloescht + +## Task-Platzhalter +- TASK_000043: Neue Doku-Dateien erstellen und verlinken +- TASK_000044: Altdoku archivieren und Hinweise einfuegen diff --git a/project-management/requirements/tasks/TASK_000043.md b/project-management/requirements/tasks/TASK_000043.md new file mode 100644 index 0000000..1613027 --- /dev/null +++ b/project-management/requirements/tasks/TASK_000043.md @@ -0,0 +1,20 @@ +ID: TASK_000043 | Version: 0.2.1 | Status: Done +By: Codex (GPT-5) + +# TASK_000043: Neue Doku-Dateien erstellen und verlinken + +## Outcome +Komplette neue Doku-Struktur mit konsistenten Inhalten und funktionierenden Links. + +## Story-Bezug +US_000040 + +## Beschreibung +- README neu strukturieren und Links auf Doku-Dateien setzen. +- GETTING_STARTED/USAGE/CONFIGURATION/ARCHITECTURE/DEVELOPMENT/DEPLOYMENT/FAQ/TROUBLESHOOTING erstellen. +- Inhalte auf Basis von Code/Skripten verifizieren. + +## Definition of Done (DoD) +- Alle Ziel-Dokumente existieren und sind vollstaendig. +- Keine widerspruechlichen Inhalte gegenueber Code. +- Interne Links funktionieren. diff --git a/project-management/requirements/tasks/TASK_000044.md b/project-management/requirements/tasks/TASK_000044.md new file mode 100644 index 0000000..2d7e651 --- /dev/null +++ b/project-management/requirements/tasks/TASK_000044.md @@ -0,0 +1,20 @@ +ID: TASK_000044 | Version: 0.2.1 | Status: Done +By: Codex (GPT-5) + +# TASK_000044: Altdoku archivieren + +## Outcome +Veraltete Dokumente sind in docs/_archive/ verschoben und klar als archiviert markiert. + +## Story-Bezug +US_000040 + +## Beschreibung +- Altdokumente identifizieren. +- In docs/_archive/ verschieben. +- Archiv-Header einfuegen. + +## Definition of Done (DoD) +- Keine Loeschung alter Dokus. +- Archiv-Header vorhanden. +- Neue Dokus referenzieren nur aktuelle Dateien.