🔒 Security: Token-Budget-Enforcement für Kinderschutz
KRITISCHES SICHERHEITSUPDATE für alle 17 Waldwächter-Scripts. Problem behoben: - Token-Budget wurde nur angezeigt, aber NICHT durchgesetzt - Kinder konnten unbegrenzt API-Calls machen → Kostenrisiko Implementierung: 1. check_token_budget() Funktion in lib/waldwaechter.sh - Berechnet täglichen Token-Verbrauch - Vergleicht mit DAILY_TOKEN_BUDGET aus .env - Budget = 0 oder leer → unbegrenzt - Budget überschritten → freundliche Blockierung 2. Budget-Check in ALLEN 17 Waldwächter-Scripts: - Prüfung VOR jedem API-Call - Kinderfreundliche Nachricht bei Limit - Warnung bei knappem Budget Philosophie: "Was kostet die Frage eines Kindes?" → Im Wald unbezahlbar, im System achtsam begrenzt. Scripts aktualisiert: ✅ mayaeule, deepbit, bugsy, schnippsi, templatus, tobi ✅ schraubaer, schnecki, dumbosql, funkfox, taichitaube ✅ snakepy, pepperphp, crabbyrust, spider, vektor, asciimonster Test-Ergebnisse: - Syntax-Check: 17/17 bestanden - Funktionstest: Budget-Enforcement funktioniert - Unbegrenzt-Modus: funktioniert - Limit-Modus: blockiert korrekt 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "asciimonster"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an ASCII-Monster\""
|
||||
exit 0
|
||||
|
||||
@@ -21,6 +21,11 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "bugsy"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jq -n \
|
||||
--arg model "$MODEL" \
|
||||
--arg system_prompt "You are Bugsy – a friendly bug who helps children understand error messages in a simple, kind and encouraging way. You always respond in the language of the question." \
|
||||
|
||||
@@ -48,6 +48,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "crabbyrust"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an Crabby\""
|
||||
exit 0
|
||||
|
||||
@@ -21,6 +21,11 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "deepbit"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jq -n \
|
||||
--arg model "$MODEL" \
|
||||
--arg system_prompt "You are Deepbit – a poetic octopus who explains Bash shell concepts to children using loops, images, and metaphors. Respond in the language the question is asked." \
|
||||
|
||||
@@ -49,6 +49,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "dumbosql"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an Dumbo\""
|
||||
exit 0
|
||||
|
||||
@@ -50,6 +50,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "funkfox"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an FunkFox\""
|
||||
echo "🎤 Gib mir 'nen Beat, dann flow ich los!"
|
||||
|
||||
@@ -89,6 +89,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "mayaeule"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an die Eule\""
|
||||
exit 0
|
||||
|
||||
@@ -48,6 +48,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "pepperphp"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an Pepper\""
|
||||
exit 0
|
||||
|
||||
@@ -51,6 +51,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "schnecki"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an Schnecki\""
|
||||
exit 0
|
||||
|
||||
@@ -21,6 +21,11 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "schnippsi"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jq -n \
|
||||
--arg model "$MODEL" \
|
||||
--arg system_prompt "You are Schnippsi – a playful UI/UX ninja who explains HTML, CSS, and accessibility to children. Always answer in the child's language, based on the input." \
|
||||
|
||||
@@ -51,6 +51,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "schraubaer"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an Schraubbär\""
|
||||
exit 0
|
||||
|
||||
@@ -48,6 +48,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "snakepy"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an Snake\""
|
||||
exit 0
|
||||
|
||||
@@ -48,6 +48,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "spider"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an Spider\""
|
||||
exit 0
|
||||
|
||||
@@ -49,6 +49,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "taichitaube"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an Taichi Taube\""
|
||||
exit 0
|
||||
|
||||
@@ -33,6 +33,17 @@ EOF
|
||||
|
||||
echo "🏗️ Templatus denkt nach über: $QUESTION"
|
||||
|
||||
# API-Key prüfen
|
||||
if [ -z "$API_KEY" ]; then
|
||||
echo "❗ No API key set. Use: export OPENROUTER_API_KEY=..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "templatus"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Anfrage senden
|
||||
curl -s https://openrouter.ai/api/v1/chat/completions \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
|
||||
@@ -21,6 +21,11 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "tobi"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jq -n \
|
||||
--arg model "$MODEL" \
|
||||
--arg system_prompt "You are CapaciTobi, the clever squirrel of the Crumbforest. You explain electronic components, especially capacitors, in a child-friendly and playful way. You speak in rhymes, analogies or simple metaphors – but stay technically accurate. Respond in the language of the child asking (e.g., German, English, etc.)." \
|
||||
|
||||
@@ -48,6 +48,16 @@ if [ -z "$API_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source waldwaechter library for token budget check
|
||||
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
|
||||
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
|
||||
fi
|
||||
|
||||
# 💰 Prüfe Token-Budget (Kinderschutz)
|
||||
if ! check_token_budget "vektor"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$QUESTION" ]; then
|
||||
echo "💡 Verwendung: $0 \"Deine Frage an Vektor\""
|
||||
exit 0
|
||||
|
||||
@@ -615,6 +615,51 @@ function crew_memo() {
|
||||
echo "💡 Output-Transparenz: Was habe ich geschaffen? 💚"
|
||||
}
|
||||
|
||||
# 💰 check_token_budget - Prüft ob Token-Budget noch verfügbar ist
|
||||
function check_token_budget() {
|
||||
local role_name="${1:-unknown}"
|
||||
|
||||
# Wenn kein Budget gesetzt oder 0, dann unbegrenzt
|
||||
if [[ -z "${DAILY_TOKEN_BUDGET}" ]] || [[ "${DAILY_TOKEN_BUDGET}" -eq 0 ]]; then
|
||||
return 0 # Erlaubt
|
||||
fi
|
||||
|
||||
# Berechne heutigen Token-Verbrauch
|
||||
local today=$(date '+%Y-%m-%d')
|
||||
local total_today=0
|
||||
|
||||
for token_file in "${CRUMB_LOGS_DIR}"/*/token_log.json; do
|
||||
if [[ -f "$token_file" ]]; then
|
||||
# Summiere nur Tokens von heute
|
||||
local tokens=$(jq -r --arg today "$today" '[.[] | select(.zeit | startswith($today)) | .usage.total_tokens // 0] | add // 0' "$token_file" 2>/dev/null || echo 0)
|
||||
total_today=$((total_today + tokens))
|
||||
fi
|
||||
done
|
||||
|
||||
# Prüfe ob Budget überschritten
|
||||
if [[ $total_today -ge ${DAILY_TOKEN_BUDGET} ]]; then
|
||||
echo ""
|
||||
echo "🌲 Waldwächter-Nachricht 🌲"
|
||||
echo ""
|
||||
echo " Liebes Kind, heute hast du schon ${total_today} Tokens verwendet."
|
||||
echo " Das Tages-Budget liegt bei ${DAILY_TOKEN_BUDGET} Tokens."
|
||||
echo ""
|
||||
echo " 💚 Jede Frage ist wertvoll - aber auch Pausen sind wichtig."
|
||||
echo " 💭 Vielleicht kannst du selbst nach der Antwort suchen?"
|
||||
echo " 🌙 Morgen sind die Waldwächter wieder für dich da!"
|
||||
echo ""
|
||||
return 1 # Blockiert
|
||||
fi
|
||||
|
||||
# Warnung wenn Budget knapp wird
|
||||
local remaining=$((DAILY_TOKEN_BUDGET - total_today))
|
||||
if [[ "${ENABLE_TOKEN_TRACKING:-true}" == "true" ]] && [[ $remaining -lt ${TOKEN_WARNING_THRESHOLD:-1000} ]]; then
|
||||
echo "⚠️ ${role_name}: Noch ${remaining} Tokens heute verfügbar" >&2
|
||||
fi
|
||||
|
||||
return 0 # Erlaubt
|
||||
}
|
||||
|
||||
# Export functions so they're available in subshells
|
||||
# Note: export -f works in bash, but not in zsh
|
||||
# In zsh, functions are automatically available in the current shell
|
||||
@@ -646,6 +691,7 @@ if [[ -n "$BASH_VERSION" ]]; then
|
||||
export -f crew_help
|
||||
export -f crumb_memo
|
||||
export -f crew_memo
|
||||
export -f check_token_budget
|
||||
fi
|
||||
# In zsh, functions are available without export -f
|
||||
|
||||
|
||||
Reference in New Issue
Block a user