feat(datastore): implement structured personal data layer (ADR 0004, ForwardAuth /family, and OpenClaw protocol)
This commit is contained in:
@@ -7,6 +7,7 @@ spec:
|
||||
addPrefix:
|
||||
prefix: /hosting
|
||||
---
|
||||
# Public Ingress for hosting.haumdaucher.de (Recipes, Public Assets)
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
@@ -16,6 +17,7 @@ metadata:
|
||||
kubernetes.io/ingress.class: "traefik"
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
kubernetes.io/tls-acme: "true"
|
||||
traefik.ingress.kubernetes.io/router.priority: "10"
|
||||
traefik.ingress.kubernetes.io/router.middlewares: minio-hosting-add-prefix@kubernetescrd
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
@@ -34,3 +36,34 @@ spec:
|
||||
- hosts:
|
||||
- hosting.haumdaucher.de
|
||||
secretName: hosting-haumdaucher-de-tls
|
||||
---
|
||||
# Protected Ingress for /family (Family Dashboards, Nutrition & Sleep Analytics)
|
||||
# Protected by Authentik ForwardAuth
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: minio-hosting-family
|
||||
namespace: minio
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "traefik"
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
kubernetes.io/tls-acme: "true"
|
||||
traefik.ingress.kubernetes.io/router.priority: "100"
|
||||
traefik.ingress.kubernetes.io/router.middlewares: auth-authentik-forwardauth@kubernetescrd,minio-hosting-add-prefix@kubernetescrd
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: hosting.haumdaucher.de
|
||||
http:
|
||||
paths:
|
||||
- path: /family
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: minio
|
||||
port:
|
||||
number: 9000
|
||||
tls:
|
||||
- hosts:
|
||||
- hosting.haumdaucher.de
|
||||
secretName: hosting-haumdaucher-de-tls
|
||||
|
||||
Binary file not shown.
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# setup-garmin-cron.sh
|
||||
# Declaratively registers the Garmin Connect Nightly Sync in OpenClaw.
|
||||
# Schedule: Daily at 03:30 Europe/Berlin (cron: 30 3 * * *)
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
NAMESPACE="${NAMESPACE:-openclaw}"
|
||||
POD_NAME="${POD_NAME:-openclaw-0}"
|
||||
CONTAINER_NAME="${CONTAINER_NAME:-openclaw}"
|
||||
|
||||
JOB_NAME="garmin-nightly-mirror"
|
||||
CRON_SCHEDULE="30 3 * * *"
|
||||
TIMEZONE="Europe/Berlin"
|
||||
TELEGRAM_GROUP="-1004326921510"
|
||||
TELEGRAM_TOPIC="20"
|
||||
|
||||
echo "=== Registering Garmin Connect Nightly Sync in OpenClaw ($POD_NAME) ==="
|
||||
|
||||
# 1. Check if job already exists
|
||||
EXISTING_ID=$(kubectl exec -n "$NAMESPACE" "$POD_NAME" -c "$CONTAINER_NAME" -- openclaw cron list 2>/dev/null | grep "$JOB_NAME" | awk '{print $1}' || true)
|
||||
|
||||
if [ -n "$EXISTING_ID" ]; then
|
||||
echo "Found existing job with ID $EXISTING_ID. Removing for idempotent recreation..."
|
||||
kubectl exec -n "$NAMESPACE" "$POD_NAME" -c "$CONTAINER_NAME" -- openclaw cron rm "$EXISTING_ID" || true
|
||||
fi
|
||||
|
||||
# 2. Add the job
|
||||
echo "Creating automation $JOB_NAME ($CRON_SCHEDULE @ $TIMEZONE)..."
|
||||
|
||||
MESSAGE=$(cat << 'EOF'
|
||||
Führe den nächtlichen Garmin Connect Sync durch.
|
||||
Vorgehen:
|
||||
1. Führe den Garmin-Sync-Befehl aus:
|
||||
uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/garmin_sync.py --days 2 --data-dir /home/node/.openclaw/wiki/main/data
|
||||
2. Aktualisiere die gerenderten Markdown-Ansichten:
|
||||
PYTHONPATH=/home/node/mop-skills/mop-skills/skills/datastore/scripts uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/render_views.py --data-dir /home/node/.openclaw/wiki/main/data --wiki-dir /home/node/.openclaw/wiki/main
|
||||
3. Git Commit & Push im Knowledge Wiki:
|
||||
cd /home/node/.openclaw/wiki/main && git add data/garmin/ entities/nutrition-log/ && git diff --staged --quiet || (git commit -m "chore(garmin): automated nightly mirror [skip ci]" && git push origin main)
|
||||
4. Finale Antwort:
|
||||
- Bei Erfolg: Gib exakt 'NO_REPLY' aus (intentional silence, kein Telegram-Spam in der Nacht).
|
||||
- Nur bei Authentifizierungsfehlern: Informiere kurz via Telegram, dass ein Garmin-Re-Auth nötig ist.
|
||||
EOF
|
||||
)
|
||||
|
||||
kubectl exec -n "$NAMESPACE" "$POD_NAME" -c "$CONTAINER_NAME" -- openclaw cron add \
|
||||
--name "$JOB_NAME" \
|
||||
--description "Nächtlicher deterministischer Spiegel der Garmin Connect Daten (Aktivitäten, Daily Summary, Schlaf) in Git JSONL" \
|
||||
--cron "$CRON_SCHEDULE" \
|
||||
--tz "$TIMEZONE" \
|
||||
--agent "fitness" \
|
||||
--model "openrouter/deepseek/deepseek-v4.1-flash" \
|
||||
--session "isolated" \
|
||||
--channel "telegram" \
|
||||
--to "$TELEGRAM_GROUP" \
|
||||
--thread-id "$TELEGRAM_TOPIC" \
|
||||
--message "$MESSAGE"
|
||||
|
||||
echo "=== Automation successfully registered! ==="
|
||||
kubectl exec -n "$NAMESPACE" "$POD_NAME" -c "$CONTAINER_NAME" -- openclaw cron list | grep "$JOB_NAME" || true
|
||||
Reference in New Issue
Block a user