Compare commits

..

5 Commits

93 changed files with 451 additions and 105 deletions

View File

@ -1,4 +1,4 @@
ID: DOC_000001 | Version: 0.1.5 | Status: Final
ID: DOC_000001 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# Projekt-Logbuch (Changelog)
@ -49,6 +49,12 @@ By: Codex (GPT-5)
| 30.12.2025 | 🎨 UI | ID: TASK_000039 Login-Text reduziert, Buttons symmetrisch, Panels/Metrics harmonisiert. By: Codex (GPT-5) |
| 30.12.2025 | 🏗️ Planning | ID: EPIC_000010/US_000034/US_000035 Update-Service v1 Migration dokumentiert. By: Codex (GPT-5) |
| 30.12.2025 | 🏗️ Planning | ID: TASK_000040/TASK_000041 fuer Enrollment und v1 Endpunkte angelegt. By: Codex (GPT-5) |
| 12.01.2026 | ⚙️ Code | ID: TASK_000040 Enrollment-Skript bereinigt und als scripts/enroll_local.py hinzugefuegt. By: Gemini CLI |
| 15.01.2026 | 🏗️ Planning | ID: EPIC_000011 und US_000036-US_000038 dokumentiert. By: Codex (GPT-5) |
| 15.01.2026 | 📝 Req | ID: Update-Doku und ENV-Beispiele an Code-Stand angeglichen. 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) |
---
## Legende

View File

@ -41,7 +41,7 @@ healthcheck:
echo "No token set; set TOKEN=... or populate $(ENV_FILE) with SKD_AUTH_TOKEN."; \
exit 1; \
fi
curl -fsS -H "X-API-Token: $(TOKEN)" "$(HEALTH_URL)" || (echo "Health check failed" && exit 1)
curl -fsS -H "Authorization: Bearer $(TOKEN)" "$(HEALTH_URL)" || (echo "Health check failed" && exit 1)
update:
$(SUDO) env PROJECT_ROOT=$(INSTALL_DIR) SERVICE_NAME=$(SERVICE) SERVICE_USER=$(SERVICE_USER) BRANCH=$(BRANCH) bash -c 'cd $(INSTALL_DIR) && ./scripts/update.sh'

View File

@ -33,10 +33,12 @@ Set in `/etc/skd/env` (see `env.example`):
- `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_URL` (default `https://update.wlkns.org`)
- `SKD_UPDATE_TOKEN` (API token for update service)
- `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_URL` (default `https://update.wlkns.org/status`)
- `SKD_UPDATE_STATUS_FILE` (default `/var/lib/skd/update_status.json`)
- `SKD_UPDATE_LOG_FILE` (default `/var/lib/skd/update_logs.jsonl`)
Notes:

View File

@ -1 +1 @@
0.2.0
0.2.1

View File

@ -133,6 +133,20 @@
<p class="text-center text-muted mt-1">Lade Update-Status...</p>
</div>
<!-- Enrollment Section -->
<div id="enrollmentSection" class="hidden" style="margin-bottom: 1rem; padding: 1rem; background: rgba(255, 255, 255, 0.05); border-radius: var(--radius-sm); border: 1px dashed var(--color-border);">
<h4 style="margin-top: 0; margin-bottom: 0.5rem;"><i data-lucide="link"></i> Gerät registrieren (Enrollment)</h4>
<p class="text-muted" style="font-size: 0.875rem; margin-bottom: 0.5rem;">
Dieses Gerät ist noch nicht beim Update-Service registriert. Bitte geben Sie einen gültigen Enrollment-Token ein.
</p>
<form id="enrollmentForm" style="display: flex; gap: 0.5rem; align-items: center;">
<input type="text" id="enrollToken" placeholder="Enrollment-Token eingeben..." required style="flex: 1;" />
<button type="submit" class="small">
<i data-lucide="check"></i> Registrieren
</button>
</form>
</div>
<div class="grid">
<button id="checkUpdateBtn" type="button">
<i data-lucide="search"></i>
@ -395,6 +409,8 @@
// Update management
async function refreshUpdateStatus() {
const statusDiv = document.getElementById('updateStatus');
// Do not clear the div if we are just refreshing to avoid flickering, maybe?
// Actually, loading spinner is fine.
statusDiv.innerHTML = '<div class="spinner" style="margin: 0 auto;"></div><p class="text-center text-muted mt-1">Lade Update-Status...</p>';
try {
@ -407,6 +423,18 @@
: data.last_status === 'failed'
? '<span class="badge error"><i data-lucide="x-circle"></i> Fehlgeschlagen</span>'
: '<span class="badge neutral"><i data-lucide="minus-circle"></i> Unbekannt</span>';
const enrolledBadge = data.enrolled
? '<span class="badge success"><i data-lucide="link"></i> Verbunden</span>'
: '<span class="badge warning"><i data-lucide="link-2-off"></i> Nicht registriert</span>';
// Toggle Enrollment Section
const enrollSection = document.getElementById('enrollmentSection');
if (data.enrolled) {
enrollSection.classList.add('hidden');
} else {
enrollSection.classList.remove('hidden');
}
statusDiv.innerHTML = `
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem;">
@ -414,6 +442,10 @@
<div class="text-muted" style="font-size: 0.75rem; text-transform: uppercase; margin-bottom: 0.25rem;">Version</div>
<div style="color: var(--color-accent); font-weight: 600;">${data.current_version}</div>
</div>
<div>
<div class="text-muted" style="font-size: 0.75rem; text-transform: uppercase; margin-bottom: 0.25rem;">Registrierung</div>
<div>${enrolledBadge}</div>
</div>
<div>
<div class="text-muted" style="font-size: 0.75rem; text-transform: uppercase; margin-bottom: 0.25rem;">Letzter Status</div>
<div>${statusBadge}</div>
@ -637,6 +669,35 @@
document.getElementById('refreshLogsBtn').addEventListener('click', refreshUpdateLogs);
document.getElementById('enrollmentForm').addEventListener('submit', async (e) => {
e.preventDefault();
const tokenInput = document.getElementById('enrollToken');
const token = tokenInput.value.trim();
const btn = e.target.querySelector('button');
if (!token) return;
const originalHTML = btn.innerHTML;
btn.innerHTML = '<div class="spinner"></div> Registriere...';
btn.disabled = true;
try {
await api('/update/enroll', {
method: 'POST',
body: JSON.stringify({ enroll_token: token })
});
showToast('Gerät erfolgreich registriert!', 'success');
tokenInput.value = '';
await refreshUpdateStatus();
} catch (err) {
showToast('Registrierung fehlgeschlagen: ' + err.message, 'error');
} finally {
btn.innerHTML = originalHTML;
btn.disabled = false;
lucide.createIcons();
}
});
// Initialize
checkSession();
checkOidcStatus();

View File

@ -1,4 +1,5 @@
ID: DOC_000006 | Version: 0.1.0 | Status: Draft
ID: DOC_000006 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Admin Token Operations

View File

@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: Update Webservice API
version: 0.1.0
version: 0.2.1
servers:
- url: https://update.wlkns.org
- url: https://staging.update.wlkns.org

View File

@ -1,4 +1,4 @@
ID: DOC_000008 | Version: 0.1.0 | Status: Draft
ID: DOC_000008 | Version: 0.2.1 | Status: Draft
# Client Quickstart

View File

@ -1,4 +1,4 @@
ID: DOC_000003 | Version: 0.1.0 | Status: Draft
ID: DOC_000003 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# OIDC End-to-End Validation (Kiddo)

View File

@ -1,4 +1,5 @@
ID: DOC_000005 | Version: 0.1.0 | Status: Draft
ID: DOC_000005 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Third-Party API Guide
@ -117,7 +118,7 @@ Common error codes:
`payload_too_large`, `status_invalid`
## Rate Limits
Limits are tiered by scope. See `docs/architecture/ARCHITECTURE.md` for current values.
Limits are tiered by scope. See `docs/architecture/openapi/paths/limits.yaml` for current values.
## Examples
Fetch manifest:

View File

@ -1,4 +1,4 @@
ID: DOC_000006 | Version: 0.1.0 | Status: Draft
ID: DOC_000006 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Update API (Kiddo Backend)
@ -8,6 +8,16 @@ Definiert interne API-Endpunkte fuer Update-Status, Check, Apply, Rollback und L
## Endpoints
### POST /update/enroll
Body (optional):
```json
{ "enroll_token": "<one-time-token>" }
```
Antwort:
```json
{ "enrolled": true, "message": "Enrollment successful" }
```
### GET /update/status
Antwort:
```json
@ -15,7 +25,8 @@ Antwort:
"current_version": "0.1.2",
"last_status": "success|failed|unknown",
"last_error": "<optional>",
"last_timestamp": "2025-12-28T12:34:56Z"
"last_timestamp": "2025-12-28T12:34:56Z",
"enrolled": true
}
```
@ -51,10 +62,18 @@ Antwort:
Antwort:
```json
[
{"timestamp":"2025-12-28T12:34:56Z","status":"success","message":"updated to 0.1.2"}
{
"timestamp": "2025-12-28T12:34:56Z",
"status": "success",
"message": "updated to 0.1.2",
"version": "0.1.2",
"device_id": "kiddo-001",
"error": null
}
]
```
## Notes
- Alle Endpunkte erfordern Auth (Session/Bearer).
- Alle Endpunkte erfordern Auth (Session-Cookie oder `Authorization: Bearer <token>`).
- Apply/Rollback starten async; UI pollt /update/status.
- `/update/enroll` speichert das Update-Token lokal (siehe `SKD_UPDATE_TOKEN_FILE`).

View File

@ -1,4 +1,4 @@
ID: DOC_000004 | Version: 0.1.0 | Status: Draft
ID: DOC_000004 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Client Update Flow (Kiddo)
@ -18,7 +18,8 @@ Beispiel:
```
## Flow (High Level)
1. Manifest abrufen (auth optional via Bearer Token).
0. Falls kein Token vorhanden ist: Enrollment durchfuehren (Pre-Shared Token -> Langzeit-Token).
1. Manifest abrufen (auth via Bearer Token).
2. `artifact_url` herunterladen.
3. SHA256 pruefen (Signatur optional).
4. In Staging-Verzeichnis entpacken.
@ -37,13 +38,14 @@ Beispiel:
## Security Notes
- Artefakte muessen checksum-verifiziert sein.
- Token-Handling ueber `SKD_UPDATE_TOKEN`.
- Token-Handling ueber `SKD_UPDATE_TOKEN` oder `SKD_UPDATE_TOKEN_FILE`.
- Enrollment nutzt einen Pre-Shared Token und speichert das Langzeit-Token lokal.
## Constraints
- Update-Service ist extern (update.wlkns.org).
- Service muss als root stoppen/starten koennen.
## Status Reporting
- Status wird per HTTP POST an `https://update.wlkns.org/status` gemeldet.
- Status wird per HTTP POST an `${SKD_UPDATE_SERVICE_URL}/v1/projects/${SKD_UPDATE_PROJECT_ID}/status` gemeldet.
- Schema siehe `docs/update-status.md`.
- Lokaler Status/Logs liegen unter `/var/lib/skd` (konfigurierbar via ENV).

View File

@ -1,4 +1,4 @@
ID: DOC_000005 | Version: 0.1.0 | Status: Draft
ID: DOC_000005 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Update Status Reporting
@ -9,17 +9,21 @@ Definiert das Status-Schema fuer Update-Resultate und den Uebertragungsweg.
## Status Schema (JSON)
```json
{
"device_id": "<hostname>",
"version": "0.1.2",
"status": "success|failed",
"error": "<optional message>",
"timestamp": "2025-12-28T12:34:56Z"
"project_id": "safe-kiddo-control",
"client_id": "<hostname>",
"version": "0.2.1",
"status": "success|failed|in_progress",
"timestamp": "2025-12-28T12:34:56Z",
"duration_ms": 1234,
"error_code": "<optional>",
"reason": "<optional>"
}
```
## Transport
- HTTP POST an `https://update.wlkns.org/status`
- Auth: Bearer Token (`SKD_UPDATE_TOKEN`)
- HTTP POST an `${SKD_UPDATE_SERVICE_URL}/v1/projects/${SKD_UPDATE_PROJECT_ID}/status`
- Auth: Bearer Token (`SKD_UPDATE_TOKEN` oder `SKD_UPDATE_TOKEN_FILE`)
## Notes
- Statusmeldungen sind best-effort; Fehler beim Senden blockieren kein Update.
- Reporting wird nur gesendet, wenn ein Update-Token vorhanden ist.

View File

@ -22,10 +22,12 @@ SKD_DEFAULT_COUNTDOWN=60
SKD_DEFAULT_SOUND=false
SKD_NOTIFY_TIMEOUT=5
# Update client configuration
SKD_UPDATE_URL=https://update.wlkns.org
SKD_UPDATE_SERVICE_URL=https://update.wlkns.org
SKD_UPDATE_PROJECT_ID=safe-kiddo-control
SKD_UPDATE_ENROLL_TOKEN=
SKD_UPDATE_TOKEN=
SKD_UPDATE_TOKEN_FILE=/var/lib/skd/update_token
SKD_UPDATE_INTERVAL=3600
SKD_UPDATE_STATUS_URL=https://update.wlkns.org/status
SKD_UPDATE_STATUS_FILE=/var/lib/skd/update_status.json
SKD_UPDATE_LOG_FILE=/var/lib/skd/update_logs.jsonl
# Set to true to test without performing real system changes

View File

@ -1,4 +1,4 @@
ID: AGENTS_000001 | Version: 0.1.0 | Status: Draft
ID: AGENTS_000001 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Repository Guidelines

View File

@ -1,4 +1,4 @@
ID: STATUS_000001 | Version: 0.1.0 | Status: Final
ID: STATUS_000001 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# Projekt-Status
@ -10,14 +10,15 @@ Sicheres, remote steuerbares System zum Sperren/Entsperren lokaler Nutzerkonten.
✅ Stabilization
## Aktueller Fokus
1. Client-Update-Mechanik planen (EPIC_000008).
2. Dokumentierter Ist-Zustand der Module.
3. Pflege der Anforderungen bei neuen Features.
1. OIDC-Validierung abschliessen (EPIC_000003 / US_000025).
2. Client-Update-Mechanik pflegen (EPIC_000008).
3. Anforderungen bei neuen Features sauber dokumentieren.
## Projekt-Tagebuch (Kurz, optional)
| Datum | Typ | Beschreibung |
|---|---|---|
| 28.12.2025 | 🏗️ Planning | Anforderungen als Epics und Stories dokumentiert. |
| 15.01.2026 | 📝 Req | Doku und ENV-Beispiele an Code-Stand angepasst. |
## Epic-Backlog (Uebersicht)
### EPIC_000001: Legacy CLI Account Control (sk.sh)
@ -114,6 +115,13 @@ Sicheres, remote steuerbares System zum Sperren/Entsperren lokaler Nutzerkonten.
- [x] US_000035: v1 Update-Endpoints und Status-Schema
- [x] TASK_000041: v1 Endpunkte im Update-Client umstellen
### EPIC_000011: Documentation and Configuration Alignment
- [x] US_000036: Doku-Versionen auf VERSION synchronisieren
- [x] US_000037: Update-API-Doku mit /update/enroll abgleichen
- [x] US_000038: ENV-Beispiele und Healthcheck-Auth angleichen
- [x] US_000039: Doku-Audit fuer verbleibende Abweichungen
- [x] TASK_000042: Doku-Audit verbleibender Dateien
## 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.
@ -122,4 +130,4 @@ Sicheres, remote steuerbares System zum Sperren/Entsperren lokaler Nutzerkonten.
## Naechste Schritte
- Anforderungen beim naechsten Feature-Start erweitern.
- OIDC-Validierung abschliessen und US_000025 auf Done setzen.
- PR vorbereiten: feature/oidc-validation (Summary, Risiko, Testschritte).
- Doku-Audit fuer weitere Abweichungen priorisieren (wenn Zeitfenster frei).

View File

@ -1,4 +1,4 @@
ID: PROJECT_STATUS_TEMPLATE | Version: 0.1.0 | Status: Draft
ID: PROJECT_STATUS_TEMPLATE | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# 📊 Projekt-Status (Template)

View File

@ -1,4 +1,4 @@
ID: SOP_000001 | Version: 0.1.0 | Status: Draft
ID: SOP_000001 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Onboarding: Arbeitsweise im Sound Architect Projekt

View File

@ -1,4 +1,4 @@
ID: SETUP_000005 | Version: 0.1.0 | Status: Draft
ID: SETUP_000005 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# 🧬 SETUP_GUIDE: Phase 0 - Project Genesis

View File

@ -1,4 +1,4 @@
ID: PROMPT_000008 | Version: 0.1.0 | Status: Draft
ID: PROMPT_000008 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Requirements Engineer Prompt

View File

@ -1,4 +1,4 @@
ID: EPIC_000001 | Version: 0.1.0 | Status: Final
ID: EPIC_000001 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# EPIC_000001: Legacy CLI Account Control (sk.sh)

View File

@ -1,4 +1,4 @@
ID: EPIC_000002 | Version: 0.1.0 | Status: Final
ID: EPIC_000002 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# EPIC_000002: Backend API Service

View File

@ -1,4 +1,4 @@
ID: EPIC_000003 | Version: 0.1.0 | Status: Final
ID: EPIC_000003 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# EPIC_000003: Authentication & Sessions

View File

@ -1,4 +1,4 @@
ID: EPIC_000004 | Version: 0.1.0 | Status: Final
ID: EPIC_000004 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# EPIC_000004: Web UI

View File

@ -1,4 +1,4 @@
ID: EPIC_000005 | Version: 0.1.0 | Status: Final
ID: EPIC_000005 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# EPIC_000005: Automation Scripts

View File

@ -1,4 +1,4 @@
ID: EPIC_000006 | Version: 0.1.0 | Status: Final
ID: EPIC_000006 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# EPIC_000006: Systemd & Deployment Artifacts

View File

@ -1,4 +1,4 @@
ID: EPIC_000007 | Version: 0.1.0 | Status: Final
ID: EPIC_000007 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# EPIC_000007: Documentation & Runbook

View File

@ -1,4 +1,4 @@
ID: EPIC_000008 | Version: 0.1.0 | Status: Draft
ID: EPIC_000008 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# EPIC_000008: Client-Side Update Mechanism

View File

@ -1,4 +1,4 @@
ID: EPIC_000009 | Version: 0.1.0 | Status: Draft
ID: EPIC_000009 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# EPIC_000009: Update Webservice (External Team)

View File

@ -1,4 +1,4 @@
ID: EPIC_000010 | Version: 0.1.5 | Status: Done
ID: EPIC_000010 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# EPIC_000010: Update-Service v1 Migration (Major Release)

View File

@ -0,0 +1,43 @@
ID: EPIC_000011 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# EPIC_000011: Documentation and Configuration Alignment
## Beschreibung
Konsolidierung der Dokumentation, Beispiel-Konfigurationen und Ops-Hinweise mit dem
aktuellen Code-Stand, inklusive Version-Synchronisierung mit der zentralen VERSION.
## Ziel / Business Value
Reduziert Integrationsfehler, sorgt fuer konsistente Bedienung und verringert Support-Aufwand.
## Mission Statement
Stelle sicher, dass Dokumente, Beispiele und Automationshinweise den realen API- und
Konfigurationsstand widerspiegeln.
## Business Value & Metriken
- Weniger Fehlkonfigurationen durch korrekte ENV-Keys und Auth-Header.
- Erfolgsmetrik: 0 bekannte Abweichungen zwischen Code und Doku in den Update/Health-Flows.
## In-Scope (Kiddo Team)
- Doku-Versionen auf VERSION ziehen.
- Update-API Doku inkl. /update/enroll und Response-Feldern aktualisieren.
- ENV-Beispiele und Makefile-Healthcheck auf aktuelle Auth-Mechanik angleichen.
## Out-of-Scope
- Funktionale Aenderungen am Auth-Flow im Backend.
- Erweiterte Validierung durch Integrationstests.
## High-Level Akzeptanzkriterien
- Doku-Header nutzen die aktuelle VERSION.
- Update-API-Doku listet alle implementierten Update-Endpunkte.
- ENV-Beispiele nutzen die im Code verwendeten Update-Variablen.
- Healthcheck-Beispiel nutzt Authorization: Bearer.
## Technische Constraints & Risiken
- Dokumentation darf keine falschen Defaults oder veraltete Endpunkte nennen.
- Audit kann weitere Abweichungen aufdecken und Folgetickets noetig machen.
## Zugeordnete User Stories
- US_000036: Doku-Versionen auf VERSION synchronisieren
- US_000037: Update-API-Doku mit /update/enroll und Response-Feldern abgleichen
- US_000038: ENV-Beispiele und Makefile-Healthcheck an Auth/Update-Config angleichen

View File

@ -1,4 +1,4 @@
ID: US_000001 | Version: 0.1.0 | Status: Final
ID: US_000001 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000001: Nutzerkonto per CLI deaktivieren

View File

@ -1,4 +1,4 @@
ID: US_000002 | Version: 0.1.0 | Status: Final
ID: US_000002 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000002: Nutzerkonto per CLI aktivieren

View File

@ -1,4 +1,4 @@
ID: US_000003 | Version: 0.1.0 | Status: Final
ID: US_000003 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000003: Health-Status abfragen

View File

@ -1,4 +1,4 @@
ID: US_000004 | Version: 0.1.0 | Status: Final
ID: US_000004 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000004: Verfuegbare Nutzer auflisten

View File

@ -1,4 +1,4 @@
ID: US_000005 | Version: 0.1.0 | Status: Final
ID: US_000005 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000005: Nutzer per API deaktivieren

View File

@ -1,4 +1,4 @@
ID: US_000006 | Version: 0.1.0 | Status: Final
ID: US_000006 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000006: Nutzer per API aktivieren

View File

@ -1,4 +1,4 @@
ID: US_000007 | Version: 0.1.0 | Status: Final
ID: US_000007 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000007: PAM-Login mit Token

View File

@ -1,4 +1,4 @@
ID: US_000008 | Version: 0.1.0 | Status: Final
ID: US_000008 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000008: OIDC-Login Flow

View File

@ -1,4 +1,4 @@
ID: US_000009 | Version: 0.1.0 | Status: Final
ID: US_000009 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000009: Autorisierung und /me-Identitaet

View File

@ -1,4 +1,4 @@
ID: US_000010 | Version: 0.1.0 | Status: Final
ID: US_000010 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000010: Index-Seite ausliefern

View File

@ -1,4 +1,4 @@
ID: US_000011 | Version: 0.1.0 | Status: Final
ID: US_000011 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000011: Virtualenv und Abhaengigkeiten erstellen

View File

@ -1,4 +1,4 @@
ID: US_000012 | Version: 0.1.0 | Status: Final
ID: US_000012 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000012: Service lokal starten

View File

@ -1,4 +1,4 @@
ID: US_000013 | Version: 0.1.0 | Status: Final
ID: US_000013 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000013: Service installieren

View File

@ -1,4 +1,4 @@
ID: US_000014 | Version: 0.1.0 | Status: Final
ID: US_000014 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000014: Service aktualisieren

View File

@ -1,4 +1,4 @@
ID: US_000015 | Version: 0.1.0 | Status: Final
ID: US_000015 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000015: Remote-Deployment durchfuehren

View File

@ -1,4 +1,4 @@
ID: US_000016 | Version: 0.1.0 | Status: Final
ID: US_000016 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000016: OIDC-Client registrieren

View File

@ -1,4 +1,4 @@
ID: US_000017 | Version: 0.1.0 | Status: Final
ID: US_000017 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000017: Systemd-Unit im Repo

View File

@ -1,4 +1,4 @@
ID: US_000018 | Version: 0.1.0 | Status: Final
ID: US_000018 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000018: Konfigurations-Templates verfuegbar

View File

@ -1,4 +1,4 @@
ID: US_000019 | Version: 0.1.0 | Status: Final
ID: US_000019 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000019: Deployment-Archiv vorhanden

View File

@ -1,4 +1,4 @@
ID: US_000020 | Version: 0.1.0 | Status: Final
ID: US_000020 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000020: Makefile-Automation bereitstellen

View File

@ -1,4 +1,4 @@
ID: US_000021 | Version: 0.1.0 | Status: Final
ID: US_000021 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000021: Konfiguration per ENV steuern

View File

@ -1,4 +1,4 @@
ID: US_000022 | Version: 0.1.0 | Status: Final
ID: US_000022 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000022: Web-UI Aktionen ausfuehren

View File

@ -1,4 +1,4 @@
ID: US_000023 | Version: 0.1.0 | Status: Final
ID: US_000023 | Version: 0.2.1 | Status: Final
By: Codex (GPT-5)
# US_000023: Runbook und Security-Hinweise dokumentieren

View File

@ -1,4 +1,4 @@
ID: US_000024 | Version: 0.1.0 | Status: Done
ID: US_000024 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000024: Watchtower Theme fuer Web-UI

View File

@ -1,4 +1,4 @@
ID: US_000025 | Version: 0.1.0 | Status: Draft
ID: US_000025 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# US_000025: OIDC End-to-End Validierung und Runbook

View File

@ -1,4 +1,4 @@
ID: US_000026 | Version: 0.1.0 | Status: Done
ID: US_000026 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000026: Client bezieht Updates (Pull)

View File

@ -1,4 +1,4 @@
ID: US_000027 | Version: 0.1.0 | Status: Done
ID: US_000027 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000027: Client verifiziert und wendet Updates an

View File

@ -1,4 +1,4 @@
ID: US_000028 | Version: 0.1.0 | Status: Done
ID: US_000028 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000028: Client meldet Update-Status

View File

@ -1,4 +1,4 @@
ID: US_000029 | Version: 0.1.0 | Status: Done
ID: US_000029 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000029: Update-Status im Web-UI anzeigen

View File

@ -1,4 +1,4 @@
ID: US_000030 | Version: 0.1.0 | Status: Done
ID: US_000030 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000030: Update-Check im Web-UI ausloesen

View File

@ -1,4 +1,4 @@
ID: US_000031 | Version: 0.1.0 | Status: Done
ID: US_000031 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000031: Update im Web-UI anstossen

View File

@ -1,4 +1,4 @@
ID: US_000032 | Version: 0.1.0 | Status: Done
ID: US_000032 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000032: Update-Logs im Web-UI anzeigen

View File

@ -1,4 +1,4 @@
ID: US_000033 | Version: 0.1.0 | Status: Done
ID: US_000033 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000033: Rollback im Web-UI anstossen

View File

@ -1,4 +1,4 @@
ID: US_000034 | Version: 0.1.5 | Status: Done
ID: US_000034 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000034: Enrollment fuer Langzeit-Token

View File

@ -1,4 +1,4 @@
ID: US_000035 | Version: 0.1.5 | Status: Done
ID: US_000035 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000035: v1 Update-Endpoints und Status-Schema

View File

@ -0,0 +1,13 @@
ID: US_000036 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000036: Doku-Versionen auf VERSION synchronisieren
Als Maintainer moechte ich, dass Doku-Header und Spezifikationen die zentrale VERSION
verwenden, damit Releases konsistent dokumentiert sind.
## Akzeptanzkriterien
- Given die VERSION ist 0.2.1
- When Doku-Header oder OpenAPI-Info Versionen angegeben sind
- Then entsprechen sie 0.2.1
- And es gibt keine widerspruechlichen 0.1.0-Header in den betroffenen Doku-Dateien

View File

@ -0,0 +1,14 @@
ID: US_000037 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000037: Update-API-Doku mit /update/enroll abgleichen
Als Betreiber moechte ich eine korrekte Update-API-Dokumentation, damit Clients die
Update-Endpunkte inkl. Enrollment korrekt nutzen.
## Akzeptanzkriterien
- Given die Backend-API implementiert /update/enroll
- When die Update-API-Doku gelesen wird
- Then /update/enroll ist beschrieben (Request und Response)
- And /update/status enthaelt das Feld enrolled
- And /update/logs beschreibt die aktuellen Felder (timestamp, status, message, version, device_id, error)

View File

@ -0,0 +1,14 @@
ID: US_000038 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000038: ENV-Beispiele und Healthcheck-Auth angleichen
Als Operator moechte ich, dass ENV-Beispiele und Healthcheck-Header mit dem aktuellen
Auth- und Update-Config-Stand uebereinstimmen, damit Deployments nicht scheitern.
## Akzeptanzkriterien
- Given das Backend akzeptiert Authorization: Bearer Tokens
- When der Healthcheck aus dem Makefile ausgefuehrt wird
- Then wird der Header Authorization: Bearer verwendet
- And env.example/README listen SKD_UPDATE_SERVICE_URL und SKD_UPDATE_PROJECT_ID
- And nicht verwendete Update-Variablen werden nicht als Pflicht-Keys aufgefuehrt

View File

@ -0,0 +1,14 @@
ID: US_000039 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# US_000039: Doku-Audit fuer verbleibende Abweichungen
Als Maintainer moechte ich eine systematische Pruefung der verbleibenden Doku-Dateien,
damit keine Versions- oder Inhaltsabweichungen zwischen Code und Dokumentation bestehen.
## Akzeptanzkriterien
- Given die zentrale VERSION ist bekannt
- When alle Doku-Dateien geprueft werden
- Then sind Header-Versionen konsistent mit VERSION
- And API-/ENV-Beschreibungen entsprechen dem aktuellen Code-Stand
- And Abweichungen sind dokumentiert oder korrigiert

View File

@ -1,4 +1,4 @@
ID: TASK_000025 | Version: 0.1.0 | Status: Blocked
ID: TASK_000025 | Version: 0.2.1 | Status: Blocked
By: Codex (GPT-5)
# TASK_000025: OIDC E2E validation

View File

@ -1,4 +1,4 @@
ID: TASK_000026 | Version: 0.1.0 | Status: Blocked
ID: TASK_000026 | Version: 0.2.1 | Status: Blocked
By: Codex (GPT-5)
# TASK_000026: OIDC runbook update

View File

@ -1,4 +1,4 @@
ID: TASK_000027 | Version: 0.1.0 | Status: Done
ID: TASK_000027 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000027: Update endpoint config

View File

@ -1,4 +1,4 @@
ID: TASK_000028 | Version: 0.1.0 | Status: Done
ID: TASK_000028 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000028: Verify and apply update

View File

@ -1,4 +1,4 @@
ID: TASK_000029 | Version: 0.1.0 | Status: Done
ID: TASK_000029 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000029: Report update status

View File

@ -1,4 +1,4 @@
ID: TASK_000030 | Version: 0.1.0 | Status: Done
ID: TASK_000030 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000030: UI update status view

View File

@ -1,4 +1,4 @@
ID: TASK_000031 | Version: 0.1.0 | Status: Done
ID: TASK_000031 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000031: UI update check trigger

View File

@ -1,4 +1,4 @@
ID: TASK_000032 | Version: 0.1.0 | Status: Done
ID: TASK_000032 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000032: UI update apply action

View File

@ -1,4 +1,4 @@
ID: TASK_000033 | Version: 0.1.0 | Status: Done
ID: TASK_000033 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000033: UI update logs view

View File

@ -1,4 +1,4 @@
ID: TASK_000034 | Version: 0.1.0 | Status: Done
ID: TASK_000034 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000034: UI rollback action

View File

@ -1,4 +1,4 @@
ID: TASK_000035 | Version: 0.1.1 | Status: Done
ID: TASK_000035 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000035: Login-Landing und Header-Version

View File

@ -1,4 +1,4 @@
ID: TASK_000036 | Version: 0.1.2 | Status: Done
ID: TASK_000036 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000036: Login-Landing und Dashboard-Redirect

View File

@ -1,4 +1,4 @@
ID: TASK_000037 | Version: 0.1.3 | Status: Done
ID: TASK_000037 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000037: OIDC-Button neben Anmelden

View File

@ -1,4 +1,4 @@
ID: TASK_000038 | Version: 0.1.4 | Status: Done
ID: TASK_000038 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000038: Logo und Favicon einbinden

View File

@ -1,4 +1,4 @@
ID: TASK_000039 | Version: 0.1.5 | Status: Done
ID: TASK_000039 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000039: Login-Text und Panel-Layout

View File

@ -1,10 +1,13 @@
ID: TASK_000040 | Version: 0.1.5 | Status: Done
ID: TASK_000040 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000040: Enrollment-Flow implementieren
## Outcome
Der Update-Client kann einmalig per Enrollment einen Langzeit-Token beziehen und lokal speichern.
Dazu stehen zwei Skripte zur Verfuegung:
- `scripts/enroll_local.py`: Enrollment ueber die lokale API (empfohlen).
- `scripts/manual_enroll.py`: Direktes Enrollment beim Update-Service (Bypass).
## Story-Bezug
US_000034

View File

@ -1,4 +1,4 @@
ID: TASK_000041 | Version: 0.1.5 | Status: Done
ID: TASK_000041 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000041: v1 Endpunkte im Update-Client umstellen

View File

@ -0,0 +1,20 @@
ID: TASK_000042 | Version: 0.2.1 | Status: Done
By: Codex (GPT-5)
# TASK_000042: Doku-Audit verbleibender Dateien
## Outcome
Alle relevanten Doku-Dateien sind geprueft und konsistent mit VERSION und Code-Stand.
## Story-Bezug
US_000039
## Beschreibung
- Liste verbleibender Doku-Dateien mit Header-Versionen pruefen.
- Abgleich mit Code fuer API- und ENV-Beschreibungen.
- Abweichungen korrigieren oder als Follow-up dokumentieren.
## Definition of Done (DoD)
- Keine verbleibenden Doku-Header mit falscher Version.
- Doku nennt nur genutzte ENV-Keys und korrekte Endpunkte.
- Ergebnis im CHANGELOG dokumentiert.

View File

@ -1,4 +1,4 @@
ID: PROMPT_000006 | Version: 0.1.0 | Status: Draft
ID: PROMPT_000006 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Restructure Prompt: Forensic Architect (Compliance Mode)

View File

@ -1,4 +1,4 @@
ID: PROMPT_000009 | Version: 0.1.0 | Status: Draft
ID: PROMPT_000009 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# Story Refactoring Prompt

View File

@ -1,4 +1,4 @@
ID: PROMPT_000007 | Version: 0.1.0 | Status: Draft
ID: PROMPT_000007 | Version: 0.2.1 | Status: Draft
By: Codex (GPT-5)
# The Stack-Master & System Architect

51
scripts/enroll_local.py Executable file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env python3
import argparse
import os
import sys
import httpx
def enroll():
parser = argparse.ArgumentParser(description="Enroll this device via the local Kiddo API")
parser.add_argument("--url", default=os.getenv("API_URL", "http://localhost:8000"), help="Local API URL")
parser.add_argument("--token", help="Enrollment Token (from update service)")
parser.add_argument("--auth", help="Local Admin Auth Token (skd_session cookie value)")
args = parser.parse_args()
# Use default token if not provided (keeping the one from the prototype for now as a fallback)
enroll_token = args.token or "739772f5-4803-4635-a2c2-454799c37534"
print(f"[*] Enrolling via local API at {args.url}")
print(f"[*] Enrollment Token: {enroll_token[:8]}...")
headers = {}
auth_token = args.auth or os.getenv("SKD_API_TOKEN")
if auth_token:
headers["Cookie"] = f"skd_session={auth_token}"
print("[*] Using provided authentication token")
else:
print("[!] No authentication token provided. Request might fail if API is protected.")
try:
response = httpx.post(
f"{args.url}/update/enroll",
json={"enroll_token": enroll_token},
headers=headers,
timeout=15.0
)
if response.status_code == 200:
print("[+] Success: Enrollment successful!")
print(f"[+] Response: {response.json()}")
elif response.status_code == 401:
print("[!] Error: Unauthorized. Please provide a valid admin auth token via --auth or SKD_API_TOKEN env.")
else:
print(f"[!] Error {response.status_code}: {response.text}")
sys.exit(1)
except Exception as e:
print(f"[!] Exception: {e}")
sys.exit(1)
if __name__ == "__main__":
enroll()

68
scripts/manual_enroll.py Executable file
View File

@ -0,0 +1,68 @@
#!/usr/bin/env python3
import argparse
import os
import sys
from pathlib import Path
# Add project root to sys.path to allow imports
PROJECT_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(PROJECT_ROOT))
import httpx
from backend.settings import get_settings
from backend.update import _ensure_parent
def main():
parser = argparse.ArgumentParser(description="Manual Enrollment Client")
parser.add_argument("--url", default="https://update.wlkns.org", help="Update Service URL")
parser.add_argument("--token", required=True, help="Enrollment Token")
parser.add_argument("--project", default="safe-kiddo-control", help="Project ID")
parser.add_argument("--insecure", action="store_true", help="Disable SSL verification")
args = parser.parse_args()
settings = get_settings()
print(f"[*] Enrolling client {os.uname().nodename}...")
print(f"[*] Service URL: {args.url}")
print(f"[*] Project ID: {args.project}")
enroll_url = f"{args.url}/v1/enroll"
payload = {
"project_id": args.project,
"client_id": os.uname().nodename,
"software_id": "safe-kiddo",
"enroll_token": args.token,
}
try:
with httpx.Client(verify=not args.insecure, timeout=10.0) as client:
response = client.post(enroll_url, json=payload)
if response.status_code != 200:
print(f"[!] Error {response.status_code}: {response.text}")
sys.exit(1)
data = response.json()
token = data.get("token")
if not token:
print("[!] Error: No token received in response")
sys.exit(1)
token_path = Path(settings.update_token_file)
_ensure_parent(token_path)
token_path.write_text(token, encoding="utf-8")
# Make sure only root/service user can read it
os.chmod(token_path, 0o600)
print(f"[+] Success! Token saved to {token_path}")
except Exception as e:
print(f"[!] Exception: {e}")
sys.exit(1)
if __name__ == "__main__":
main()