[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"public-branding":3,"docs-list-de":8,"public-ads-config":17774},{"siteName":4,"primaryColor":5,"accentColor":6,"faviconUrl":7,"logoUrl":7},"KiroCloud","#ffffff","#888888","",[9,557,967,2005,2338,3707,5169,5485,6041,6617,6880,7331,7966,8514,8668,9716,10817,13644,14021,14450,14950,16265,17095],{"id":10,"title":11,"author":12,"body":13,"category":547,"description":548,"extension":549,"lastUpdated":12,"meta":550,"navigation":551,"order":552,"path":553,"readTime":12,"seo":554,"stem":555,"__hash__":556},"docs\u002Fdocs\u002Fde\u002Fadd-bot.md","Einen Bot hinzufügen",null,{"type":14,"value":15,"toc":536},"minimark",[16,21,25,28,31,36,39,63,65,69,108,122,124,128,175,191,193,197,200,224,235,237,241,315,318,320,324,327,409,411,415,418,440,442,446],[17,18,20],"h1",{"id":19},"einen-discord-bot-zu-kirocloud-hinzufügen","Einen Discord-Bot zu KiroCloud hinzufügen",[22,23,24],"p",{},"Mit KiroCloud kannst du deinen eigenen benutzerdefinierten Discord-Bot in wenigen Minuten hosten, verwalten und mit leistungsstarken Modulen wie Tickets, Minecraft-Verknüpfung, Auto-Moderation und Level-Systemen ausstatten.",[22,26,27],{},"In dieser Anleitung erfährst du, wie du eine neue Bot-Applikation im Discord Developer Portal erstellst, die erforderlichen Berechtigungen und Intents konfigurierst und den Bot sicher mit KiroCloud verbindest.",[29,30],"hr",{},[32,33,35],"h2",{"id":34},"voraussetzungen","Voraussetzungen",[22,37,38],{},"Bevor du beginnst, stelle sicher, dass du folgende Voraussetzungen erfüllst:",[40,41,42,51,54],"ul",{},[43,44,45,46,50],"li",{},"Einen aktiven ",[47,48,49],"strong",{},"Discord-Account",".",[43,52,53],{},"Einen eigenen Discord-Server (oder Administrator-Rechte auf einem bestehenden Server), auf dem der Bot hinzugefügt werden soll.",[43,55,56,57,50],{},"Einen registrierten Account auf ",[58,59,4],"a",{"href":60,"rel":61},"https:\u002F\u002Fkirocloud.de",[62],"nofollow",[29,64],{},[32,66,68],{"id":67},"schritt-1-applikation-im-discord-developer-portal-erstellen","Schritt 1: Applikation im Discord Developer Portal erstellen",[70,71,72,80,83,89,101],"ol",{},[43,73,74,75,50],{},"Öffne das offizielle ",[58,76,79],{"href":77,"rel":78},"https:\u002F\u002Fdiscord.com\u002Fdevelopers\u002Fapplications",[62],"Discord Developer Portal",[43,81,82],{},"Melde dich mit deinem Discord-Account an.",[43,84,85,86,50],{},"Klicke oben rechts auf die Schaltfläche ",[47,87,88],{},"\"New Application\"",[43,90,91,92,95,96,100],{},"Vergib einen ",[47,93,94],{},"Namen"," für deine Applikation (z. B. ",[97,98,99],"code",{},"MeinServer Bot",") und akzeptiere die Discord Developer Terms of Service.",[43,102,103,104,107],{},"Klicke auf ",[47,105,106],{},"\"Create\"",". Du gelangst nun zur Übersicht deiner neuen Applikation.",[109,110,111],"blockquote",{},[22,112,113,117,118,121],{},[114,115,116],"span",{},"!TIP","\nUnter ",[47,119,120],{},"General Information"," kannst du ein Profilbild (App Icon) und eine kurze Beschreibung für deinen Bot hinterlegen.",[29,123],{},[32,125,127],{"id":126},"schritt-2-bot-nutzer-erstellen-privileged-gateway-intents-aktivieren","Schritt 2: Bot-Nutzer erstellen & Privileged Gateway Intents aktivieren",[70,129,130,136,142,169],{},[43,131,132,133,50],{},"Navigiere im linken Menü zum Reiter ",[47,134,135],{},"\"Bot\"",[43,137,138,139,50],{},"Scrolle nach unten zum Abschnitt ",[47,140,141],{},"Privileged Gateway Intents",[43,143,144,145],{},"Aktiviere zwingend die folgenden drei Schalter:\n",[40,146,147,153,159],{},[43,148,149,152],{},[47,150,151],{},"Presence Intent:"," Ermöglicht dem Bot das Erkennen von Online-Status und Aktivitäten.",[43,154,155,158],{},[47,156,157],{},"Server Members Intent:"," Notwendig für Willkommensnachrichten, Auto-Rollen, Minecraft-Synchronisation und Mitgliederlisten.",[43,160,161,164,165,168],{},[47,162,163],{},"Message Content Intent:"," Zwingend erforderlich, damit der Bot Chat-Befehle (z. B. ",[97,166,167],{},"!ticketpanel","), AutoMod-Filter und Textnachrichten verarbeiten kann.",[43,170,171,172,50],{},"Klicke unten auf ",[47,173,174],{},"\"Save Changes\"",[109,176,177],{},[22,178,179,182,183,186,187,190],{},[114,180,181],{},"!IMPORTANT","\nOhne die Aktivierung von ",[47,184,185],{},"Message Content Intent"," und ",[47,188,189],{},"Server Members Intent"," können zentrale Funktionen wie Tickets, Moderation und Verifikation nicht ordnungsgemäß ausgeführt werden!",[29,192],{},[32,194,196],{"id":195},"schritt-3-bot-token-generieren-und-kopieren","Schritt 3: Bot-Token generieren und kopieren",[22,198,199],{},"Der Bot-Token fungiert als Passwort für deinen Discord-Bot. KiroCloud benötigt diesen Token, um sich in deinem Namen mit den Discord-Gateways zu verbinden.",[70,201,202,208,215,218],{},[43,203,204,205,207],{},"Bleibe im Reiter ",[47,206,135],{}," des Developer Portals.",[43,209,210,211,214],{},"Klicke unter dem Benutzernamen des Bots auf ",[47,212,213],{},"\"Reset Token\""," (bzw. \"View Token\").",[43,216,217],{},"Bestätige eventuell die Zwei-Faktor-Authentifizierung (2FA) deines Discord-Accounts.",[43,219,103,220,223],{},[47,221,222],{},"\"Copy\"",", um den Token in deine Zwischenablage zu kopieren.",[109,225,226],{},[22,227,228,231,234],{},[114,229,230],{},"!CAUTION",[47,232,233],{},"Halte deinen Bot-Token absolut geheim!"," Gib ihn niemals an Dritte weiter und lade ihn nicht in öffentliche GitHub-Repositories hoch. KiroCloud speichert deinen Token sicher und verschlüsselt (AES-256).",[29,236],{},[32,238,240],{"id":239},"schritt-4-bot-in-kirocloud-registrieren","Schritt 4: Bot in KiroCloud registrieren",[70,242,243,251,262,268,310],{},[43,244,245,246,50],{},"Öffne das ",[58,247,250],{"href":248,"rel":249},"https:\u002F\u002Fkirocloud.de\u002Fdashboard",[62],"KiroCloud Dashboard",[43,252,253,254,257,258,261],{},"Klicke auf die Schaltfläche ",[47,255,256],{},"\"Bot hinzufügen\""," (",[97,259,260],{},"+",").",[43,263,264,267],{},[47,265,266],{},"Schritt 1 (Server auswählen):"," Wähle den Discord-Server aus der Liste aus, auf dem der Bot primär laufen soll.",[43,269,270,273],{},[47,271,272],{},"Schritt 2 (Konfiguration eingeben):",[40,274,275,281,294,304],{},[43,276,277,280],{},[47,278,279],{},"Bot-Name:"," Wähle einen Anzeigenamen für das KiroCloud Dashboard.",[43,282,283,286,287,290,291,261],{},[47,284,285],{},"Application \u002F Client-ID:"," Kopiere die ",[97,288,289],{},"Application ID"," aus dem Discord Developer Portal (unter ",[292,293,120],"em",{},[43,295,296,299,300,303],{},[47,297,298],{},"Client Secret:"," (Optional) Kopiere das ",[97,301,302],{},"Client Secret"," für erweiterte OAuth2-Integrationen.",[43,305,306,309],{},[47,307,308],{},"Bot-Token:"," Füge den in Schritt 3 kopierten Token ein.",[43,311,103,312,50],{},[47,313,314],{},"\"Bot erstellen\"",[22,316,317],{},"KiroCloud validiert den Token sofort gegen die Discord API und richtet eine isolierte Laufzeitumgebung für deinen Bot ein.",[29,319],{},[32,321,323],{"id":322},"schritt-5-bot-auf-deinen-discord-server-einladen","Schritt 5: Bot auf deinen Discord-Server einladen",[22,325,326],{},"Damit dein Bot auf deinem Discord-Server aktiv werden kann, musst du ihn mit den passenden Rechten einladen:",[70,328,329,335,355,406],{},[43,330,331,332,50],{},"Gehe im Discord Developer Portal zum Reiter ",[47,333,334],{},"\"OAuth2\" > \"URL Generator\"",[43,336,337,338,341,342],{},"Wähle unter ",[47,339,340],{},"Scopes",":\n",[40,343,344,349],{},[43,345,346],{},[97,347,348],{},"bot",[43,350,351,354],{},[97,352,353],{},"applications.commands"," (für Slash-Commands)",[43,356,337,357,360,361],{},[47,358,359],{},"Bot Permissions"," die erforderlichen Berechtigungen aus:\n",[40,362,363,373],{},[43,364,365,368,369,372],{},[292,366,367],{},"Empfohlen:"," ",[97,370,371],{},"Administrator"," (für reibungslose Funktion aller Module)",[43,374,375,368,378,381,382,381,385,381,388,381,391,381,394,381,397,381,400,381,403,50],{},[292,376,377],{},"Alternativ (Minimal):",[97,379,380],{},"Manage Roles",", ",[97,383,384],{},"Manage Channels",[97,386,387],{},"Kick Members",[97,389,390],{},"Ban Members",[97,392,393],{},"Send Messages",[97,395,396],{},"Embed Links",[97,398,399],{},"Attach Files",[97,401,402],{},"Read Message History",[97,404,405],{},"Manage Messages",[43,407,408],{},"Kopiere die generierte URL ganz unten, öffne sie im Browser und wähle deinen Discord-Server aus, um den Bot zu autorisieren.",[29,410],{},[32,412,414],{"id":413},"schritt-6-bot-starten-status-prüfen","Schritt 6: Bot starten & Status prüfen",[22,416,417],{},"Nach erfolgreicher Verknüpfung wirst du direkt in das Bot-Dashboard weitergeleitet.",[70,419,420,426,433],{},[43,421,422,423,50],{},"Klicke oben rechts im Bot-Dashboard auf ",[47,424,425],{},"\"Bot starten\"",[43,427,428,429,432],{},"Im integrierten ",[47,430,431],{},"Live-Terminal"," kannst du den Verbindungsaufbau in Echtzeit mitverfolgen.",[43,434,435,436,439],{},"Sobald der Status-Badge auf ",[47,437,438],{},"\"Online\""," wechselt, ist dein Bot einsatzbereit und reagiert auf Discord-Interaktionen!",[29,441],{},[32,443,445],{"id":444},"häufige-fehlerquellen-troubleshooting","Häufige Fehlerquellen & Troubleshooting",[447,448,449,466],"table",{},[450,451,452],"thead",{},[453,454,455,460,463],"tr",{},[456,457,459],"th",{"align":458},"left","Problem",[456,461,462],{"align":458},"Ursache",[456,464,465],{"align":458},"Lösung",[467,468,469,486,504,517],"tbody",{},[453,470,471,480,483],{},[472,473,474],"td",{"align":458},[47,475,476,477],{},"Status wechselt auf ",[97,478,479],{},"Error",[472,481,482],{"align":458},"Ungültiger oder zurückgesetzter Bot-Token",[472,484,485],{"align":458},"Überprüfe den Token im Discord Developer Portal und aktualisiere ihn in den Bot-Einstellungen.",[453,487,488,493,498],{},[472,489,490],{"align":458},[47,491,492],{},"Bot reagiert nicht auf Nachrichten",[472,494,495,497],{"align":458},[97,496,185],{}," deaktiviert",[472,499,500,501,50],{"align":458},"Aktiviere den Intent im Discord Developer Portal unter ",[292,502,503],{},"Bot > Privileged Gateway Intents",[453,505,506,511,514],{},[472,507,508],{"align":458},[47,509,510],{},"Bot kann keine Rollen vergeben",[472,512,513],{"align":458},"Rollenhierarchie in Discord falsch",[472,515,516],{"align":458},"Ziehe die Bot-Rolle in den Discord-Servereinstellungen über alle Rollen, die der Bot verwalten soll.",[453,518,519,524,530],{},[472,520,521],{"align":458},[47,522,523],{},"Slash-Commands tauchen nicht auf",[472,525,526,527,529],{"align":458},"Scope ",[97,528,353],{}," fehlt",[472,531,532,533,535],{"align":458},"Lade den Bot über den OAuth2-URL-Generator mit aktiviertem ",[97,534,353],{},"-Scope erneut ein.",{"title":7,"searchDepth":537,"depth":537,"links":538},2,[539,540,541,542,543,544,545,546],{"id":34,"depth":537,"text":35},{"id":67,"depth":537,"text":68},{"id":126,"depth":537,"text":127},{"id":195,"depth":537,"text":196},{"id":239,"depth":537,"text":240},{"id":322,"depth":537,"text":323},{"id":413,"depth":537,"text":414},{"id":444,"depth":537,"text":445},"getting-started","Schritt-für-Schritt-Anleitung zur Erstellung und Verknüpfung deines Discord-Bots mit KiroCloud.","md",{},true,1,"\u002Fdocs\u002Fde\u002Fadd-bot",{"title":11,"description":548},"docs\u002Fde\u002Fadd-bot","entncKqb3RX9hOeRMpCnzYXj98ssX1Dg461h7kps6d4",{"id":558,"title":559,"author":12,"body":560,"category":958,"description":959,"extension":549,"lastUpdated":12,"meta":960,"navigation":551,"order":962,"path":963,"readTime":12,"seo":964,"stem":965,"__hash__":966},"docs\u002Fdocs\u002Fde\u002Fapi-keys.md","API Keys",{"type":14,"value":561,"toc":947},[562,566,569,573,576,615,623,627,634,656,660,663,695,709,713,718,774,778,836,840,895,899,943],[17,563,565],{"id":564},"api-automatisierung","API & Automatisierung",[22,567,568],{},"KiroCloud bietet eine moderne, REST-basierte API an, mit der du externe Tools, Bots oder CI\u002FCD-Pipelines an dein Dashboard anbinden kannst. Alle Anfragen erfordern eine sichere Authentifizierung via API-Schlüssel.",[32,570,572],{"id":571},"_1-api-schlüssel-erstellen","1. API-Schlüssel erstellen",[22,574,575],{},"API-Schlüssel werden direkt in deinem Benutzer-Dashboard generiert:",[70,577,578,584,589,592,599,606],{},[43,579,580,581,50],{},"Navigiere im Dashboard zu ",[47,582,583],{},"Einstellungen > Entwickler & API-Schlüssel",[43,585,103,586,50],{},[47,587,588],{},"Neuen API-Schlüssel erstellen",[43,590,591],{},"Vergib einen eindeutigen Namen (z. B. \"GitHub Actions Deployment\").",[43,593,594,595,598],{},"Bestimme die ",[47,596,597],{},"Gültigkeitsdauer"," (in Tagen).",[43,600,601,602,605],{},"Wähle die benötigten ",[47,603,604],{},"Berechtigungen (Scopes)",". Vergib stets nur die Rechte, die für den jeweiligen Anwendungsfall zwingend nötig sind (Prinzip der geringsten Privilegien \u002F Least Privilege).",[43,607,103,608,186,611,614],{},[47,609,610],{},"Erstellen",[47,612,613],{},"kopiere den Token sofort",". Er wird dir danach nie wieder im Klartext angezeigt!",[109,616,617],{},[22,618,619,622],{},[114,620,621],{},"!WARNING","\nTeile deinen API-Schlüssel niemals öffentlich. Sollte ein Schlüssel kompromittiert werden, lösche (revoke) ihn umgehend im Dashboard.",[32,624,626],{"id":625},"_2-authentifizierung","2. Authentifizierung",[22,628,629,630,633],{},"Um sich bei der KiroCloud-API zu authentifizieren, musst du den API-Schlüssel im ",[97,631,632],{},"Authorization","-Header als Bearer-Token mitsenden.",[635,636,640],"pre",{"className":637,"code":638,"language":639,"meta":7,"style":7},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","Authorization: Bearer kiro_sec_DEIN_SCHLUESSEL\n","bash",[97,641,642],{"__ignoreMap":7},[114,643,645,649,653],{"class":644,"line":552},"line",[114,646,648],{"class":647},"sBMFI","Authorization:",[114,650,652],{"class":651},"sfazB"," Bearer",[114,654,655],{"class":651}," kiro_sec_DEIN_SCHLUESSEL\n",[32,657,659],{"id":658},"_3-berechtigungen-scopes","3. Berechtigungen (Scopes)",[22,661,662],{},"Je nachdem, was du automatisieren willst, benötigt dein API-Schlüssel spezifische Scopes:",[40,664,665,671,677,683,689],{},[43,666,667,670],{},[97,668,669],{},"bots:read"," - Erlaubt das Auslesen des Status und der Metriken deiner eigenen Discord Bots.",[43,672,673,676],{},[97,674,675],{},"bots:write"," - Erlaubt Steuerungsbefehle (Starten, Stoppen, Neustarten) und das Senden von Embeds.",[43,678,679,682],{},[97,680,681],{},"tickets:read"," - Erlaubt das Einsehen deiner eigenen Support-Tickets.",[43,684,685,688],{},[97,686,687],{},"tickets:write"," - Erlaubt das Eröffnen neuer Support-Tickets und Antworten.",[43,690,691,694],{},[97,692,693],{},"servers:read"," - Erlaubt die Abfrage des Serverstatus für verknüpfte Minecraft-Server.",[109,696,697],{},[22,698,699,701,702,704,705,708],{},[114,700,116],{},"\nEin API Key mit dem Scope ",[97,703,675],{}," kann beispielsweise nach einem erfolgreichen GitHub Actions Build automatisch einen Neustart des Bots über ",[97,706,707],{},"POST \u002Fapi\u002Fv1\u002Fbots\u002F:id\u002Frestart"," auslösen.",[32,710,712],{"id":711},"_4-beispiel-aufrufe","4. Beispiel-Aufrufe",[714,715,717],"h3",{"id":716},"curl","cURL",[635,719,721],{"className":637,"code":720,"language":639,"meta":7,"style":7},"curl -X GET \"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1\u002Fbots\" \\\n  -H \"Authorization: Bearer kiro_sec_YOUR_API_KEY\" \\\n  -H \"Accept: application\u002Fjson\"\n",[97,722,723,747,761],{"__ignoreMap":7},[114,724,725,727,730,733,737,740,743],{"class":644,"line":552},[114,726,716],{"class":647},[114,728,729],{"class":651}," -X",[114,731,732],{"class":651}," GET",[114,734,736],{"class":735},"sMK4o"," \"",[114,738,739],{"class":651},"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1\u002Fbots",[114,741,742],{"class":735},"\"",[114,744,746],{"class":745},"sTEyZ"," \\\n",[114,748,749,752,754,757,759],{"class":644,"line":537},[114,750,751],{"class":651},"  -H",[114,753,736],{"class":735},[114,755,756],{"class":651},"Authorization: Bearer kiro_sec_YOUR_API_KEY",[114,758,742],{"class":735},[114,760,746],{"class":745},[114,762,764,766,768,771],{"class":644,"line":763},3,[114,765,751],{"class":651},[114,767,736],{"class":735},[114,769,770],{"class":651},"Accept: application\u002Fjson",[114,772,773],{"class":735},"\"\n",[714,775,777],{"id":776},"nodejs-javascript-fetch","Node.js \u002F JavaScript (Fetch)",[635,779,783],{"className":780,"code":781,"language":782,"meta":7,"style":7},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const response = await fetch(\"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1\u002Fbots\", {\n  method: \"GET\",\n  headers: {\n    \"Authorization\": \"Bearer kiro_sec_YOUR_API_KEY\",\n    \"Content-Type\": \"application\u002Fjson\"\n  }\n});\nconst data = await response.json();\nconsole.log(data);\n","javascript",[97,784,785,790,795,800,806,812,818,824,830],{"__ignoreMap":7},[114,786,787],{"class":644,"line":552},[114,788,789],{},"const response = await fetch(\"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1\u002Fbots\", {\n",[114,791,792],{"class":644,"line":537},[114,793,794],{},"  method: \"GET\",\n",[114,796,797],{"class":644,"line":763},[114,798,799],{},"  headers: {\n",[114,801,803],{"class":644,"line":802},4,[114,804,805],{},"    \"Authorization\": \"Bearer kiro_sec_YOUR_API_KEY\",\n",[114,807,809],{"class":644,"line":808},5,[114,810,811],{},"    \"Content-Type\": \"application\u002Fjson\"\n",[114,813,815],{"class":644,"line":814},6,[114,816,817],{},"  }\n",[114,819,821],{"class":644,"line":820},7,[114,822,823],{},"});\n",[114,825,827],{"class":644,"line":826},8,[114,828,829],{},"const data = await response.json();\n",[114,831,833],{"class":644,"line":832},9,[114,834,835],{},"console.log(data);\n",[714,837,839],{"id":838},"python-requests","Python (Requests)",[635,841,845],{"className":842,"code":843,"language":844,"meta":7,"style":7},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import requests\n\nurl = \"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1\u002Fbots\"\nheaders = {\n    \"Authorization\": \"Bearer kiro_sec_YOUR_API_KEY\",\n    \"Content-Type\": \"application\u002Fjson\"\n}\n\nresponse = requests.get(url, headers=headers)\nprint(response.json())\n","python",[97,846,847,852,857,862,867,871,875,880,884,889],{"__ignoreMap":7},[114,848,849],{"class":644,"line":552},[114,850,851],{},"import requests\n",[114,853,854],{"class":644,"line":537},[114,855,856],{"emptyLinePlaceholder":551},"\n",[114,858,859],{"class":644,"line":763},[114,860,861],{},"url = \"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1\u002Fbots\"\n",[114,863,864],{"class":644,"line":802},[114,865,866],{},"headers = {\n",[114,868,869],{"class":644,"line":808},[114,870,805],{},[114,872,873],{"class":644,"line":814},[114,874,811],{},[114,876,877],{"class":644,"line":820},[114,878,879],{},"}\n",[114,881,882],{"class":644,"line":826},[114,883,856],{"emptyLinePlaceholder":551},[114,885,886],{"class":644,"line":832},[114,887,888],{},"response = requests.get(url, headers=headers)\n",[114,890,892],{"class":644,"line":891},10,[114,893,894],{},"print(response.json())\n",[32,896,898],{"id":897},"_5-fehlerbehebung","5. Fehlerbehebung",[447,900,901,911],{},[450,902,903],{},[453,904,905,908],{},[456,906,907],{},"Status Code",[456,909,910],{},"Möglicher Grund",[467,912,913,923,933],{},[453,914,915,920],{},[472,916,917],{},[97,918,919],{},"401 Unauthorized",[472,921,922],{},"API-Schlüssel fehlt, ist ungültig oder abgelaufen.",[453,924,925,930],{},[472,926,927],{},[97,928,929],{},"403 Forbidden",[472,931,932],{},"Der API-Schlüssel hat nicht den erforderlichen Scope für diesen Endpunkt.",[453,934,935,940],{},[472,936,937],{},[97,938,939],{},"429 Too Many Requests",[472,941,942],{},"Rate-Limit überschritten.",[944,945,946],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":7,"searchDepth":537,"depth":537,"links":948},[949,950,951,952,957],{"id":571,"depth":537,"text":572},{"id":625,"depth":537,"text":626},{"id":658,"depth":537,"text":659},{"id":711,"depth":537,"text":712,"children":953},[954,955,956],{"id":716,"depth":763,"text":717},{"id":776,"depth":763,"text":777},{"id":838,"depth":763,"text":839},{"id":897,"depth":537,"text":898},"api","Verwalte und nutze KiroCloud API-Schlüssel für die Automatisierung",{"icon":961},"i-lucide-key",0,"\u002Fdocs\u002Fde\u002Fapi-keys",{"title":559,"description":959},"docs\u002Fde\u002Fapi-keys","cvpaNNLdXuHptlZr8Cn6t2obzr_HccjR_pACQL58ky0",{"id":968,"title":969,"author":12,"body":970,"category":12,"description":978,"extension":549,"lastUpdated":12,"meta":1993,"navigation":551,"order":962,"path":1994,"readTime":12,"seo":1995,"stem":2003,"__hash__":2004},"docs\u002Fdocs\u002Fde\u002Fbot-token-security.md","[object Object]",{"type":14,"value":971,"toc":1985},[972,976,979,986,988,992,995,1006,1010,1017,1019,1023,1030,1048,1056,1058,1062,1069,1928,1941,1943,1947,1979,1982],[17,973,975],{"id":974},"discord-bot-token-security-envelope-encryption-aes-256-gcm-secret-management","Discord Bot Token Security: Envelope Encryption (AES-256-GCM) & Secret Management",[22,977,978],{},"Ein kompromittierter Discord-Bot-Token verleiht Angreifern uneingeschränkten Zugriff auf die Bot-Identität, private Server, Chatverläufe und Administrator-Befehle. Wenn ein Bot auf Tausenden von Servern aktiv ist, kann ein Token-Leak zur Zerstörung von Communities (Raid-Attacken) und zum dauerhaften Bann der Applikation durch Discord führen.",[22,980,981,982,985],{},"In diesem Leitfaden stellen wir die kryptografische Sicherheitsarchitektur vor, wie sie auf KiroCloud zur Absicherung sensibler Anmeldedaten im Ruhezustand (Data at Rest) mit ",[47,983,984],{},"AES-256-GCM Envelope Encryption"," implementiert ist.",[29,987],{},[32,989,991],{"id":990},"_1-warum-plaintext-speicherung-in-datenbanken-inakzeptabel-ist","1. Warum Plaintext-Speicherung in Datenbanken inakzeptabel ist",[22,993,994],{},"Das Speichern von Bot-Tokens in Klartext in einer Datenbank (wie PostgreSQL oder MySQL) stellt ein extremes Sicherheitsrisiko dar:",[40,996,997,1000,1003],{},[43,998,999],{},"Datenbank-Dumps und Backups enthalten unverschlüsselte Tokens.",[43,1001,1002],{},"SQL-Injection-Schwachstellen können direkt alle Tokens im System kompromittieren.",[43,1004,1005],{},"Entwickler oder Administratoren mit Lesezugriff auf die Datenbank können fremde Bots kapern.",[714,1007,1009],{"id":1008},"warum-einfaches-hashing-wie-bcrypt-oder-argon2-nicht-funktioniert","Warum einfaches Hashing (wie bcrypt oder Argon2) nicht funktioniert:",[22,1011,1012,1013,1016],{},"Passwörter werden gehasht, weil man sie nach dem Login nie wieder im Klartext benötigt. Ein Bot-Token muss jedoch von der Host-Plattform im Klartext verwendet werden, um sich am Discord Gateway anzumelden. Daher ist eine ",[47,1014,1015],{},"starke, authentifizierte symmetrische Verschlüsselung"," zwingend erforderlich.",[29,1018],{},[32,1020,1022],{"id":1021},"_2-der-goldstandard-authenticated-encryption-mit-aes-256-gcm","2. Der Goldstandard: Authenticated Encryption mit AES-256-GCM",[22,1024,1025,1026,1029],{},"Wir verwenden den Algorithmus ",[47,1027,1028],{},"AES-256-GCM"," (Galois\u002FCounter Mode). GCM bietet zwei entscheidende Vorteile:",[70,1031,1032,1038],{},[43,1033,1034,1037],{},[47,1035,1036],{},"Vertraulichkeit:"," Niemand ohne den Master-Schlüssel kann den Token entschlüsseln.",[43,1039,1040,1043,1044,1047],{},[47,1041,1042],{},"Integrität & Authentizität:"," Durch einen 128-Bit Authentifizierungs-Tag (",[97,1045,1046],{},"authTag",") wird jeder Manipulationsversuch an der verschlüsselten Zeichenkette sofort erkannt und führt zum Abbruch der Entschlüsselung.",[635,1049,1054],{"className":1050,"code":1052,"language":1053},[1051],"language-text","                  ┌───────────────────────────────┐\n                  │    Discord Bot Token (Plain)  │\n                  └───────────────┬───────────────┘\n                                  │\n                  ┌───────────────▼───────────────┐\n                  │     AES-256-GCM Verschlüssler  │ ◄─── Master Key (256-bit)\n                  └───────┬───────────────┬───────┘ ◄─── Random IV (96-bit)\n                          │               │\n            ┌─────────────▼─────┐   ┌─────▼─────────────┐\n            │ Verschlüsselter   │   │ Authentication    │\n            │ Ciphertext        │   │ Tag (128-bit)     │\n            └─────────────┬─────┘   └─────┬─────────────┘\n                          │               │\n                          ▼               ▼\n                  ┌───────────────────────────────┐\n                  │     PostgreSQL Datensatz      │\n                  │ (token_enc, token_iv, token_tag)\n                  └───────────────────────────────┘\n","text",[97,1055,1052],{"__ignoreMap":7},[29,1057],{},[32,1059,1061],{"id":1060},"_3-vollständige-nodejs-krypto-implementierung","3. Vollständige Node.js Krypto-Implementierung",[22,1063,1064,1065,1068],{},"Nutze das native ",[97,1066,1067],{},"node:crypto","-Modul für kryptografisch sichere Ver- und Entschlüsselung:",[635,1070,1074],{"className":1071,"code":1072,"language":1073,"meta":7,"style":7},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import crypto from 'node:crypto';\n\nconst ALGORITHM = 'aes-256-gcm';\nconst IV_LENGTH = 12; \u002F\u002F 96 Bit für GCM Standard\n\nexport interface EncryptedSecret {\n  ciphertext: string;\n  iv: string;\n  authTag: string;\n}\n\n\u002F**\n * Verschlüsselt ein Geheimnis mit AES-256-GCM\n *\u002F\nexport function encryptSecret(plaintext: string, masterKeyHex: string): EncryptedSecret {\n  const key = Buffer.from(masterKeyHex, 'hex');\n  if (key.length !== 32) {\n    throw new Error('Master key must be 32 bytes (256 bits).');\n  }\n\n  \u002F\u002F WICHTIG: Jeder Vorgang MUSS einen kryptografisch zufälligen IV verwenden!\n  const iv = crypto.randomBytes(IV_LENGTH);\n  const cipher = crypto.createCipheriv(ALGORITHM, key, iv);\n\n  let ciphertext = cipher.update(plaintext, 'utf8', 'hex');\n  ciphertext += cipher.final('hex');\n\n  const authTag = cipher.getAuthTag().toString('hex');\n\n  return {\n    ciphertext,\n    iv: iv.toString('hex'),\n    authTag,\n  };\n}\n\n\u002F**\n * Entschlüsselt ein Geheimnis und verifiziert dessen Integrität\n *\u002F\nexport function decryptSecret(encrypted: EncryptedSecret, masterKeyHex: string): string {\n  const key = Buffer.from(masterKeyHex, 'hex');\n  const iv = Buffer.from(encrypted.iv, 'hex');\n  const authTag = Buffer.from(encrypted.authTag, 'hex');\n\n  const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);\n  decipher.setAuthTag(authTag);\n\n  let plaintext = decipher.update(encrypted.ciphertext, 'hex', 'utf8');\n  plaintext += decipher.final('utf8'); \u002F\u002F Wirft Fehler bei manipuliertem Ciphertext!\n\n  return plaintext;\n}\n","typescript",[97,1075,1076,1099,1103,1124,1144,1148,1162,1176,1187,1198,1202,1207,1213,1219,1225,1265,1303,1331,1356,1361,1366,1372,1399,1433,1438,1481,1508,1513,1550,1555,1563,1572,1598,1606,1612,1617,1622,1627,1633,1638,1671,1702,1738,1773,1778,1811,1830,1835,1880,1909,1914,1923],{"__ignoreMap":7},[114,1077,1078,1082,1085,1088,1091,1093,1096],{"class":644,"line":552},[114,1079,1081],{"class":1080},"s7zQu","import",[114,1083,1084],{"class":745}," crypto ",[114,1086,1087],{"class":1080},"from",[114,1089,1090],{"class":735}," '",[114,1092,1067],{"class":651},[114,1094,1095],{"class":735},"'",[114,1097,1098],{"class":735},";\n",[114,1100,1101],{"class":644,"line":537},[114,1102,856],{"emptyLinePlaceholder":551},[114,1104,1105,1109,1112,1115,1117,1120,1122],{"class":644,"line":763},[114,1106,1108],{"class":1107},"spNyl","const",[114,1110,1111],{"class":745}," ALGORITHM ",[114,1113,1114],{"class":735},"=",[114,1116,1090],{"class":735},[114,1118,1119],{"class":651},"aes-256-gcm",[114,1121,1095],{"class":735},[114,1123,1098],{"class":735},[114,1125,1126,1128,1131,1133,1137,1140],{"class":644,"line":802},[114,1127,1108],{"class":1107},[114,1129,1130],{"class":745}," IV_LENGTH ",[114,1132,1114],{"class":735},[114,1134,1136],{"class":1135},"sbssI"," 12",[114,1138,1139],{"class":735},";",[114,1141,1143],{"class":1142},"sHwdD"," \u002F\u002F 96 Bit für GCM Standard\n",[114,1145,1146],{"class":644,"line":808},[114,1147,856],{"emptyLinePlaceholder":551},[114,1149,1150,1153,1156,1159],{"class":644,"line":814},[114,1151,1152],{"class":1080},"export",[114,1154,1155],{"class":1107}," interface",[114,1157,1158],{"class":647}," EncryptedSecret",[114,1160,1161],{"class":735}," {\n",[114,1163,1164,1168,1171,1174],{"class":644,"line":820},[114,1165,1167],{"class":1166},"swJcz","  ciphertext",[114,1169,1170],{"class":735},":",[114,1172,1173],{"class":647}," string",[114,1175,1098],{"class":735},[114,1177,1178,1181,1183,1185],{"class":644,"line":826},[114,1179,1180],{"class":1166},"  iv",[114,1182,1170],{"class":735},[114,1184,1173],{"class":647},[114,1186,1098],{"class":735},[114,1188,1189,1192,1194,1196],{"class":644,"line":832},[114,1190,1191],{"class":1166},"  authTag",[114,1193,1170],{"class":735},[114,1195,1173],{"class":647},[114,1197,1098],{"class":735},[114,1199,1200],{"class":644,"line":891},[114,1201,879],{"class":735},[114,1203,1205],{"class":644,"line":1204},11,[114,1206,856],{"emptyLinePlaceholder":551},[114,1208,1210],{"class":644,"line":1209},12,[114,1211,1212],{"class":1142},"\u002F**\n",[114,1214,1216],{"class":644,"line":1215},13,[114,1217,1218],{"class":1142}," * Verschlüsselt ein Geheimnis mit AES-256-GCM\n",[114,1220,1222],{"class":644,"line":1221},14,[114,1223,1224],{"class":1142}," *\u002F\n",[114,1226,1228,1230,1233,1237,1240,1244,1246,1248,1251,1254,1256,1258,1261,1263],{"class":644,"line":1227},15,[114,1229,1152],{"class":1080},[114,1231,1232],{"class":1107}," function",[114,1234,1236],{"class":1235},"s2Zo4"," encryptSecret",[114,1238,1239],{"class":735},"(",[114,1241,1243],{"class":1242},"sHdIc","plaintext",[114,1245,1170],{"class":735},[114,1247,1173],{"class":647},[114,1249,1250],{"class":735},",",[114,1252,1253],{"class":1242}," masterKeyHex",[114,1255,1170],{"class":735},[114,1257,1173],{"class":647},[114,1259,1260],{"class":735},"):",[114,1262,1158],{"class":647},[114,1264,1161],{"class":735},[114,1266,1268,1271,1274,1277,1280,1282,1284,1286,1289,1291,1293,1296,1298,1301],{"class":644,"line":1267},16,[114,1269,1270],{"class":1107},"  const",[114,1272,1273],{"class":745}," key",[114,1275,1276],{"class":735}," =",[114,1278,1279],{"class":745}," Buffer",[114,1281,50],{"class":735},[114,1283,1087],{"class":1235},[114,1285,1239],{"class":1166},[114,1287,1288],{"class":745},"masterKeyHex",[114,1290,1250],{"class":735},[114,1292,1090],{"class":735},[114,1294,1295],{"class":651},"hex",[114,1297,1095],{"class":735},[114,1299,1300],{"class":1166},")",[114,1302,1098],{"class":735},[114,1304,1306,1309,1311,1314,1316,1319,1322,1325,1328],{"class":644,"line":1305},17,[114,1307,1308],{"class":1080},"  if",[114,1310,257],{"class":1166},[114,1312,1313],{"class":745},"key",[114,1315,50],{"class":735},[114,1317,1318],{"class":745},"length",[114,1320,1321],{"class":735}," !==",[114,1323,1324],{"class":1135}," 32",[114,1326,1327],{"class":1166},") ",[114,1329,1330],{"class":735},"{\n",[114,1332,1334,1337,1340,1343,1345,1347,1350,1352,1354],{"class":644,"line":1333},18,[114,1335,1336],{"class":1080},"    throw",[114,1338,1339],{"class":735}," new",[114,1341,1342],{"class":1235}," Error",[114,1344,1239],{"class":1166},[114,1346,1095],{"class":735},[114,1348,1349],{"class":651},"Master key must be 32 bytes (256 bits).",[114,1351,1095],{"class":735},[114,1353,1300],{"class":1166},[114,1355,1098],{"class":735},[114,1357,1359],{"class":644,"line":1358},19,[114,1360,817],{"class":735},[114,1362,1364],{"class":644,"line":1363},20,[114,1365,856],{"emptyLinePlaceholder":551},[114,1367,1369],{"class":644,"line":1368},21,[114,1370,1371],{"class":1142},"  \u002F\u002F WICHTIG: Jeder Vorgang MUSS einen kryptografisch zufälligen IV verwenden!\n",[114,1373,1375,1377,1380,1382,1385,1387,1390,1392,1395,1397],{"class":644,"line":1374},22,[114,1376,1270],{"class":1107},[114,1378,1379],{"class":745}," iv",[114,1381,1276],{"class":735},[114,1383,1384],{"class":745}," crypto",[114,1386,50],{"class":735},[114,1388,1389],{"class":1235},"randomBytes",[114,1391,1239],{"class":1166},[114,1393,1394],{"class":745},"IV_LENGTH",[114,1396,1300],{"class":1166},[114,1398,1098],{"class":735},[114,1400,1402,1404,1407,1409,1411,1413,1416,1418,1421,1423,1425,1427,1429,1431],{"class":644,"line":1401},23,[114,1403,1270],{"class":1107},[114,1405,1406],{"class":745}," cipher",[114,1408,1276],{"class":735},[114,1410,1384],{"class":745},[114,1412,50],{"class":735},[114,1414,1415],{"class":1235},"createCipheriv",[114,1417,1239],{"class":1166},[114,1419,1420],{"class":745},"ALGORITHM",[114,1422,1250],{"class":735},[114,1424,1273],{"class":745},[114,1426,1250],{"class":735},[114,1428,1379],{"class":745},[114,1430,1300],{"class":1166},[114,1432,1098],{"class":735},[114,1434,1436],{"class":644,"line":1435},24,[114,1437,856],{"emptyLinePlaceholder":551},[114,1439,1441,1444,1447,1449,1451,1453,1456,1458,1460,1462,1464,1467,1469,1471,1473,1475,1477,1479],{"class":644,"line":1440},25,[114,1442,1443],{"class":1107},"  let",[114,1445,1446],{"class":745}," ciphertext",[114,1448,1276],{"class":735},[114,1450,1406],{"class":745},[114,1452,50],{"class":735},[114,1454,1455],{"class":1235},"update",[114,1457,1239],{"class":1166},[114,1459,1243],{"class":745},[114,1461,1250],{"class":735},[114,1463,1090],{"class":735},[114,1465,1466],{"class":651},"utf8",[114,1468,1095],{"class":735},[114,1470,1250],{"class":735},[114,1472,1090],{"class":735},[114,1474,1295],{"class":651},[114,1476,1095],{"class":735},[114,1478,1300],{"class":1166},[114,1480,1098],{"class":735},[114,1482,1484,1486,1489,1491,1493,1496,1498,1500,1502,1504,1506],{"class":644,"line":1483},26,[114,1485,1167],{"class":745},[114,1487,1488],{"class":735}," +=",[114,1490,1406],{"class":745},[114,1492,50],{"class":735},[114,1494,1495],{"class":1235},"final",[114,1497,1239],{"class":1166},[114,1499,1095],{"class":735},[114,1501,1295],{"class":651},[114,1503,1095],{"class":735},[114,1505,1300],{"class":1166},[114,1507,1098],{"class":735},[114,1509,1511],{"class":644,"line":1510},27,[114,1512,856],{"emptyLinePlaceholder":551},[114,1514,1516,1518,1521,1523,1525,1527,1530,1533,1535,1538,1540,1542,1544,1546,1548],{"class":644,"line":1515},28,[114,1517,1270],{"class":1107},[114,1519,1520],{"class":745}," authTag",[114,1522,1276],{"class":735},[114,1524,1406],{"class":745},[114,1526,50],{"class":735},[114,1528,1529],{"class":1235},"getAuthTag",[114,1531,1532],{"class":1166},"()",[114,1534,50],{"class":735},[114,1536,1537],{"class":1235},"toString",[114,1539,1239],{"class":1166},[114,1541,1095],{"class":735},[114,1543,1295],{"class":651},[114,1545,1095],{"class":735},[114,1547,1300],{"class":1166},[114,1549,1098],{"class":735},[114,1551,1553],{"class":644,"line":1552},29,[114,1554,856],{"emptyLinePlaceholder":551},[114,1556,1558,1561],{"class":644,"line":1557},30,[114,1559,1560],{"class":1080},"  return",[114,1562,1161],{"class":735},[114,1564,1566,1569],{"class":644,"line":1565},31,[114,1567,1568],{"class":745},"    ciphertext",[114,1570,1571],{"class":735},",\n",[114,1573,1575,1578,1580,1582,1584,1586,1588,1590,1592,1594,1596],{"class":644,"line":1574},32,[114,1576,1577],{"class":1166},"    iv",[114,1579,1170],{"class":735},[114,1581,1379],{"class":745},[114,1583,50],{"class":735},[114,1585,1537],{"class":1235},[114,1587,1239],{"class":1166},[114,1589,1095],{"class":735},[114,1591,1295],{"class":651},[114,1593,1095],{"class":735},[114,1595,1300],{"class":1166},[114,1597,1571],{"class":735},[114,1599,1601,1604],{"class":644,"line":1600},33,[114,1602,1603],{"class":745},"    authTag",[114,1605,1571],{"class":735},[114,1607,1609],{"class":644,"line":1608},34,[114,1610,1611],{"class":735},"  };\n",[114,1613,1615],{"class":644,"line":1614},35,[114,1616,879],{"class":735},[114,1618,1620],{"class":644,"line":1619},36,[114,1621,856],{"emptyLinePlaceholder":551},[114,1623,1625],{"class":644,"line":1624},37,[114,1626,1212],{"class":1142},[114,1628,1630],{"class":644,"line":1629},38,[114,1631,1632],{"class":1142}," * Entschlüsselt ein Geheimnis und verifiziert dessen Integrität\n",[114,1634,1636],{"class":644,"line":1635},39,[114,1637,1224],{"class":1142},[114,1639,1641,1643,1645,1648,1650,1653,1655,1657,1659,1661,1663,1665,1667,1669],{"class":644,"line":1640},40,[114,1642,1152],{"class":1080},[114,1644,1232],{"class":1107},[114,1646,1647],{"class":1235}," decryptSecret",[114,1649,1239],{"class":735},[114,1651,1652],{"class":1242},"encrypted",[114,1654,1170],{"class":735},[114,1656,1158],{"class":647},[114,1658,1250],{"class":735},[114,1660,1253],{"class":1242},[114,1662,1170],{"class":735},[114,1664,1173],{"class":647},[114,1666,1260],{"class":735},[114,1668,1173],{"class":647},[114,1670,1161],{"class":735},[114,1672,1674,1676,1678,1680,1682,1684,1686,1688,1690,1692,1694,1696,1698,1700],{"class":644,"line":1673},41,[114,1675,1270],{"class":1107},[114,1677,1273],{"class":745},[114,1679,1276],{"class":735},[114,1681,1279],{"class":745},[114,1683,50],{"class":735},[114,1685,1087],{"class":1235},[114,1687,1239],{"class":1166},[114,1689,1288],{"class":745},[114,1691,1250],{"class":735},[114,1693,1090],{"class":735},[114,1695,1295],{"class":651},[114,1697,1095],{"class":735},[114,1699,1300],{"class":1166},[114,1701,1098],{"class":735},[114,1703,1705,1707,1709,1711,1713,1715,1717,1719,1721,1723,1726,1728,1730,1732,1734,1736],{"class":644,"line":1704},42,[114,1706,1270],{"class":1107},[114,1708,1379],{"class":745},[114,1710,1276],{"class":735},[114,1712,1279],{"class":745},[114,1714,50],{"class":735},[114,1716,1087],{"class":1235},[114,1718,1239],{"class":1166},[114,1720,1652],{"class":745},[114,1722,50],{"class":735},[114,1724,1725],{"class":745},"iv",[114,1727,1250],{"class":735},[114,1729,1090],{"class":735},[114,1731,1295],{"class":651},[114,1733,1095],{"class":735},[114,1735,1300],{"class":1166},[114,1737,1098],{"class":735},[114,1739,1741,1743,1745,1747,1749,1751,1753,1755,1757,1759,1761,1763,1765,1767,1769,1771],{"class":644,"line":1740},43,[114,1742,1270],{"class":1107},[114,1744,1520],{"class":745},[114,1746,1276],{"class":735},[114,1748,1279],{"class":745},[114,1750,50],{"class":735},[114,1752,1087],{"class":1235},[114,1754,1239],{"class":1166},[114,1756,1652],{"class":745},[114,1758,50],{"class":735},[114,1760,1046],{"class":745},[114,1762,1250],{"class":735},[114,1764,1090],{"class":735},[114,1766,1295],{"class":651},[114,1768,1095],{"class":735},[114,1770,1300],{"class":1166},[114,1772,1098],{"class":735},[114,1774,1776],{"class":644,"line":1775},44,[114,1777,856],{"emptyLinePlaceholder":551},[114,1779,1781,1783,1786,1788,1790,1792,1795,1797,1799,1801,1803,1805,1807,1809],{"class":644,"line":1780},45,[114,1782,1270],{"class":1107},[114,1784,1785],{"class":745}," decipher",[114,1787,1276],{"class":735},[114,1789,1384],{"class":745},[114,1791,50],{"class":735},[114,1793,1794],{"class":1235},"createDecipheriv",[114,1796,1239],{"class":1166},[114,1798,1420],{"class":745},[114,1800,1250],{"class":735},[114,1802,1273],{"class":745},[114,1804,1250],{"class":735},[114,1806,1379],{"class":745},[114,1808,1300],{"class":1166},[114,1810,1098],{"class":735},[114,1812,1814,1817,1819,1822,1824,1826,1828],{"class":644,"line":1813},46,[114,1815,1816],{"class":745},"  decipher",[114,1818,50],{"class":735},[114,1820,1821],{"class":1235},"setAuthTag",[114,1823,1239],{"class":1166},[114,1825,1046],{"class":745},[114,1827,1300],{"class":1166},[114,1829,1098],{"class":735},[114,1831,1833],{"class":644,"line":1832},47,[114,1834,856],{"emptyLinePlaceholder":551},[114,1836,1838,1840,1843,1845,1847,1849,1851,1853,1855,1857,1860,1862,1864,1866,1868,1870,1872,1874,1876,1878],{"class":644,"line":1837},48,[114,1839,1443],{"class":1107},[114,1841,1842],{"class":745}," plaintext",[114,1844,1276],{"class":735},[114,1846,1785],{"class":745},[114,1848,50],{"class":735},[114,1850,1455],{"class":1235},[114,1852,1239],{"class":1166},[114,1854,1652],{"class":745},[114,1856,50],{"class":735},[114,1858,1859],{"class":745},"ciphertext",[114,1861,1250],{"class":735},[114,1863,1090],{"class":735},[114,1865,1295],{"class":651},[114,1867,1095],{"class":735},[114,1869,1250],{"class":735},[114,1871,1090],{"class":735},[114,1873,1466],{"class":651},[114,1875,1095],{"class":735},[114,1877,1300],{"class":1166},[114,1879,1098],{"class":735},[114,1881,1883,1886,1888,1890,1892,1894,1896,1898,1900,1902,1904,1906],{"class":644,"line":1882},49,[114,1884,1885],{"class":745},"  plaintext",[114,1887,1488],{"class":735},[114,1889,1785],{"class":745},[114,1891,50],{"class":735},[114,1893,1495],{"class":1235},[114,1895,1239],{"class":1166},[114,1897,1095],{"class":735},[114,1899,1466],{"class":651},[114,1901,1095],{"class":735},[114,1903,1300],{"class":1166},[114,1905,1139],{"class":735},[114,1907,1908],{"class":1142}," \u002F\u002F Wirft Fehler bei manipuliertem Ciphertext!\n",[114,1910,1912],{"class":644,"line":1911},50,[114,1913,856],{"emptyLinePlaceholder":551},[114,1915,1917,1919,1921],{"class":644,"line":1916},51,[114,1918,1560],{"class":1080},[114,1920,1842],{"class":745},[114,1922,1098],{"class":735},[114,1924,1926],{"class":644,"line":1925},52,[114,1927,879],{"class":735},[109,1929,1930],{},[22,1931,1932,1934,1937,1938,50],{},[114,1933,230],{},[47,1935,1936],{},"Niemals denselben IV wiederverwenden:"," In GCM führt die Wiederverwendung desselben Initialisierungsvektors mit demselben Schlüssel zum vollständigen Verlust der Authentizität und kann die Wiederherstellung des Klartexts ermöglichen. Erzeuge den IV ausnahmslos mit ",[97,1939,1940],{},"crypto.randomBytes(12)",[29,1942],{},[32,1944,1946],{"id":1945},"_4-secret-management-key-rotation","4. Secret Management & Key Rotation",[70,1948,1949,1962],{},[43,1950,1951,1954,1955,1958,1959,261],{},[47,1952,1953],{},"Master-Key niemals im Git-Repository speichern:"," Der AES-Schlüssel gehört ausschließlich in strikt geschützte Umgebungsvariablen (",[97,1956,1957],{},".env"," oder Vault-Systeme) mit restriktiven Dateirechten (",[97,1960,1961],{},"chmod 600",[43,1963,1964,1967,1968],{},[47,1965,1966],{},"Schlüssel-Rotation (Re-Encryption):"," Wenn der Master-Schlüssel erneuert werden muss, führt ein Hintergrunddienst eine sequenzielle Re-Encryption durch:\n",[40,1969,1970,1973,1976],{},[43,1971,1972],{},"Entschlüsseln mit altem Schlüssel",[43,1974,1975],{},"Verschlüsseln mit neuem Schlüssel",[43,1977,1978],{},"Transaktionales Update in der Datenbank",[22,1980,1981],{},"Auf KiroCloud geschieht diese Verschlüsselung vollautomatisch beim Eintragen von Discord-Tokens, wodurch selbst im Falle eines physischen Datenbankdiebstahls kein einziger Bot-Token kompromittiert werden kann.",[944,1983,1984],{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":537,"depth":537,"links":1986},[1987,1990,1991,1992],{"id":990,"depth":537,"text":991,"children":1988},[1989],{"id":1008,"depth":763,"text":1009},{"id":1021,"depth":537,"text":1022},{"id":1060,"depth":537,"text":1061},{"id":1945,"depth":537,"text":1946},{},"\u002Fdocs\u002Fde\u002Fbot-token-security",{"title":1996,"description":978},{"Discord Bot Token Security":1997,"description":1998,"category":1999,"order":552,"author":2000,"readTime":2001,"lastUpdated":2002},"Envelope Encryption (AES-256-GCM) & Secret Management","Sicherheitsarchitektur zum Schutz sensibler Bot-Tokens. Envelope Encryption mit AES-256-GCM, Schlüsselrotation und sichere Datenbank-Speicherung.","security","Luca Lichtenwald","13 min","2026-10-09","docs\u002Fde\u002Fbot-token-security","LixuaSl5UldVn9lmiX5azvcI3D46EORfgTrysL5ud20",{"id":2006,"title":2007,"author":12,"body":2008,"category":547,"description":2332,"extension":549,"lastUpdated":12,"meta":2333,"navigation":551,"order":537,"path":2334,"readTime":12,"seo":2335,"stem":2336,"__hash__":2337},"docs\u002Fdocs\u002Fde\u002Fdashboard-overview.md","Dashboard-Übersicht",{"type":14,"value":2009,"toc":2325},[2010,2014,2021,2023,2027,2030,2093,2100,2102,2106,2109,2178,2186,2188,2192,2195,2246,2248,2252,2255,2299,2301,2305],[17,2011,2013],{"id":2012},"dashboard-übersicht","Dashboard Übersicht",[22,2015,2016,2017,2020],{},"Das ",[47,2018,2019],{},"KiroCloud Bot-Dashboard"," ist die zentrale Schaltzentrale für die Steuerung, Überwachung und Konfiguration deiner Discord-Bots. Dank moderner WebSocket-Technologie und einer responsiven Benutzeroberfläche behältst du den aktuellen Status, Server-Metriken und Live-Logs jederzeit latenzfrei im Blick.",[29,2022],{},[32,2024,2026],{"id":2025},"_1-bot-status-schnellaktionen-quick-actions","1. Bot-Status & Schnellaktionen (Quick Actions)",[22,2028,2029],{},"Im oberen Bereich des Dashboards findest du die wichtigsten Kontroll- und Statusanzeigen deines Bots:",[40,2031,2032,2062,2087],{},[43,2033,2034,2037],{},[47,2035,2036],{},"Status-Badge:",[40,2038,2039,2045,2051,2057],{},[43,2040,2041,2044],{},[97,2042,2043],{},"Online"," (Grün): Der Bot ist mit dem Discord-Gateway verbunden und verarbeitet Events.",[43,2046,2047,2050],{},[97,2048,2049],{},"Offline"," (Grau): Der Bot ist gestoppt und verbraucht keine Ressourcen.",[43,2052,2053,2056],{},[97,2054,2055],{},"Starting"," (Gelb): Der Bot initialisiert Module und stellt die Gateway-Verbindung her.",[43,2058,2059,2061],{},[97,2060,479],{}," (Rot): Beim Starten ist ein Fehler aufgetreten (z. B. ungültiger Token oder fehlende Intents).",[43,2063,2064,2067],{},[47,2065,2066],{},"Steuerungs-Buttons:",[40,2068,2069,2075,2081],{},[43,2070,2071,2074],{},[47,2072,2073],{},"Starten:"," Fährt den Bot-Container hoch und stellt die Discord-Verbindung her.",[43,2076,2077,2080],{},[47,2078,2079],{},"Stoppen:"," Beendet den Bot-Prozess sicher.",[43,2082,2083,2086],{},[47,2084,2085],{},"Neustarten:"," Führt einen Warm-Restart durch, um geänderte Einstellungen oder Module neu zu laden.",[43,2088,2089,2092],{},[47,2090,2091],{},"Server-Info:"," Zeigt das verbundene Discord-Guild-Icon, den Servernamen und die Bot-Client-ID an.",[109,2094,2095],{},[22,2096,2097,2099],{},[114,2098,116],{},"\nDie meisten Moduländerungen (wie Ticket-Texte oder Willkommensnachrichten) werden dank unseres dynamischen Config-Cachings in Echtzeit übernommen, ohne dass ein Bot-Neustart erforderlich ist!",[29,2101],{},[32,2103,2105],{"id":2104},"_2-ressourcen-monitoring-telemetrie","2. Ressourcen-Monitoring & Telemetrie",[22,2107,2108],{},"KiroCloud überwacht die Performance deines Bots kontinuierlich und stellt die Metriken in übersichtlichen Widgets dar:",[447,2110,2111,2124],{},[450,2112,2113],{},[453,2114,2115,2118,2121],{},[456,2116,2117],{"align":458},"Metrik",[456,2119,2120],{"align":458},"Beschreibung",[456,2122,2123],{"align":458},"Empfohlener Richtwert",[467,2125,2126,2139,2152,2165],{},[453,2127,2128,2133,2136],{},[472,2129,2130],{"align":458},[47,2131,2132],{},"CPU-Auslastung (%)",[472,2134,2135],{"align":458},"Aktuelle Prozessor-Nutzung des Bot-Prozesses",[472,2137,2138],{"align":458},"Unter 15% im Normalbetrieb",[453,2140,2141,2146,2149],{},[472,2142,2143],{"align":458},[47,2144,2145],{},"RAM-Nutzung (MB \u002F %)",[472,2147,2148],{"align":458},"Belegter Arbeitsspeicher der isolierten Node.js-Laufzeit",[472,2150,2151],{"align":458},"Typisch 60–250 MB (je nach Servergröße)",[453,2153,2154,2159,2162],{},[472,2155,2156],{"align":458},[47,2157,2158],{},"Gateway Ping (ms)",[472,2160,2161],{"align":458},"Latenzzeit zwischen KiroCloud und den Discord-WebSocket-Servern",[472,2163,2164],{"align":458},"10–60 ms",[453,2166,2167,2172,2175],{},[472,2168,2169],{"align":458},[47,2170,2171],{},"Commands Executed",[472,2173,2174],{"align":458},"Gesamtzahl der erfolgreich ausgeführten Slash- und Chat-Befehle",[472,2176,2177],{"align":458},"Statistischer Zähler",[109,2179,2180],{},[22,2181,2182,2185],{},[114,2183,2184],{},"!NOTE","\nSollte der RAM-Verbrauch deines Bots ungewöhnlich stark ansteigen, prüfe bitte aktive Caches oder Bild-Generierungsfunktionen in benutzerdefinierten Modulen.",[29,2187],{},[32,2189,2191],{"id":2190},"_3-integriertes-live-terminal-log-viewer","3. Integriertes Live-Terminal & Log-Viewer",[22,2193,2194],{},"Über das WebSocket-gestützte Live-Terminal (basierend auf Xterm.js) kannst du die Konsole deines Bots in Echtzeit verfolgen:",[40,2196,2197,2203,2209],{},[43,2198,2199,2202],{},[47,2200,2201],{},"Latenzfreies Streaming:"," Logs werden per WebSocket direkt vom Backend an den Browser gepusht.",[43,2204,2205,2208],{},[47,2206,2207],{},"Historie:"," Die letzten 500 Log-Einträge bleiben im Buffer gespeichert und stehen auch nach einem Tab-Wechsel bereit.",[43,2210,2211,2214],{},[47,2212,2213],{},"Farbcodierte Log-Level:",[40,2215,2216,2222,2228,2234,2240],{},[43,2217,2218,2221],{},[97,2219,2220],{},"\\x1b[36m INFO"," (Cyan): Allgemeine System- und Startmeldungen.",[43,2223,2224,2227],{},[97,2225,2226],{},"\\x1b[33m WARN"," (Gelb): Warnungen (z. B. Rate-Limit Annäherungen, fehlende optionale Berechtigungen).",[43,2229,2230,2233],{},[97,2231,2232],{},"\\x1b[31m ERROR"," (Rot): Kritische Fehler und unhandled Exceptions.",[43,2235,2236,2239],{},[97,2237,2238],{},"\\x1b[32m CMD"," (Grün): Ausgeführte Benutzer-Befehle und Interaktionen.",[43,2241,2242,2245],{},[97,2243,2244],{},"\\x1b[35m EVT"," (Magenta): Discord-Gateway-Events (z. B. Member Join, Channel Create).",[29,2247],{},[32,2249,2251],{"id":2250},"_4-modul-verwaltung-konfiguration","4. Modul-Verwaltung & Konfiguration",[22,2253,2254],{},"Über die Navigations-Tabs im Dashboard kannst du spezialisierte Module per Klick aktivieren und detailliert anpassen:",[40,2256,2257,2263,2269,2275,2281,2287,2293],{},[43,2258,2259,2262],{},[47,2260,2261],{},"Tickets:"," Vollständiges Support-Ticket-System mit Dropdown-Kategorien, Claiming und Transcripts.",[43,2264,2265,2268],{},[47,2266,2267],{},"Verify (Verifikation):"," Schutz vor Raids durch Captcha-, Button- oder Minecraft-Account-Verifikation.",[43,2270,2271,2274],{},[47,2272,2273],{},"Welcome & Leave:"," Begrüßungs- und Verabschiedungsnachrichten mit dynamischem Embed-Builder.",[43,2276,2277,2280],{},[47,2278,2279],{},"AutoMod & Security:"," Automatischer Spam-Schutz, Anti-Invite-Filter, Caps-Sperre und Mass-Mention-Schutz.",[43,2282,2283,2286],{},[47,2284,2285],{},"Level & Coins:"," Community-Gamification mit XP-Tracking, Rängen und virtuellem Server-Shop.",[43,2288,2289,2292],{},[47,2290,2291],{},"Giveaways:"," Vollautomatische Gewinnspiele mit Reaktions-\u002FButton-Teilnahme und Auslosung.",[43,2294,2295,2298],{},[47,2296,2297],{},"Custom Commands & Schedules:"," Eigene Textbefehle und automatisierte Cronjobs zu festen Uhrzeiten.",[29,2300],{},[32,2302,2304],{"id":2303},"_5-server-management-bot-schedules","5. Server-Management & Bot-Schedules",[40,2306,2307,2313,2319],{},[43,2308,2309,2312],{},[47,2310,2311],{},"Server-Übersicht:"," Sieh auf einen Blick, auf welchen Servern dein Bot autorisiert ist, und generiere maßgeschneiderte Einladungslinks.",[43,2314,2315,2318],{},[47,2316,2317],{},"Bot-Schedules (Cronjobs):"," Plane wiederkehrende Aufgaben – wie tägliche Ankündigungen, automatisches Bereinigen von temporären Kanälen oder periodische Statusmeldungen.",[43,2320,2321,2324],{},[47,2322,2323],{},"Team-Management:"," Teile den Dashboard-Zugriff mit deinen Teammitgliedern (Moderatoren oder Entwicklern), ohne deinen Bot-Token weitergeben zu müssen.",{"title":7,"searchDepth":537,"depth":537,"links":2326},[2327,2328,2329,2330,2331],{"id":2025,"depth":537,"text":2026},{"id":2104,"depth":537,"text":2105},{"id":2190,"depth":537,"text":2191},{"id":2250,"depth":537,"text":2251},{"id":2303,"depth":537,"text":2304},"Lerne das KiroCloud Bot-Dashboard, Live-Logs, Modul-Verwaltung und Telemetrie kennen.",{},"\u002Fdocs\u002Fde\u002Fdashboard-overview",{"title":2007,"description":2332},"docs\u002Fde\u002Fdashboard-overview","QFBtpuMjaRov1ybCcW5wjgRl7Dab15Am9pezZM1efdg",{"id":2339,"title":969,"author":12,"body":2340,"category":12,"description":3695,"extension":549,"lastUpdated":12,"meta":3696,"navigation":551,"order":962,"path":3697,"readTime":12,"seo":3698,"stem":3705,"__hash__":3706},"docs\u002Fdocs\u002Fde\u002Fdiscord-memory-leaks.md",{"type":14,"value":2341,"toc":3683},[2342,2346,2353,2360,2362,2366,2369,2373,2380,2397,2400,2404,2415,2507,2509,2513,2520,2962,2966,3012,3014,3018,3024,3449,3451,3455,3466,3587,3593,3595,3599,3680],[17,2343,2345],{"id":2344},"discordjs-memory-leaks-beheben-v8-heap-analyse-cache-strategien","Discord.js Memory Leaks beheben: V8 Heap-Analyse & Cache-Strategien",[22,2347,2348,2349,2352],{},"Discord-Bots, die auf großen Servern betrieben werden oder über Wochen ohne Neustart laufen, leiden häufig unter schleichendem RAM-Wachstum. Ein Bot, der nach dem Start 120 MB Arbeitsspeicher belegt, kann innerhalb weniger Tage mehrere Gigabyte verbrauchen, bis die Node.js-Runtime den Prozess mit einem ",[97,2350,2351],{},"FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory"," beendet.",[22,2354,2355,2356,2359],{},"In diesem Leitfaden analysieren wir die tatsächlichen Ursachen von Speicherlecks in ",[97,2357,2358],{},"discord.js v14",", demonstrieren die V8 Heap-Snapshot-Analyse und implementieren produktionsreife Cache-Sweeping-Strategien.",[29,2361],{},[32,2363,2365],{"id":2364},"_1-die-hauptursachen-für-memory-leaks-in-discord-bots","1. Die Hauptursachen für Memory Leaks in Discord-Bots",[22,2367,2368],{},"In JavaScript verhindert der automatische Garbage Collector (GC), dass nicht mehr referenzierter Speicher weiter belegt bleibt. Ein Memory Leak entsteht dann, wenn Objekte im Heap verbleiben, weil unbeabsichtigte Referenzen aus dem Root-Scope (z. B. globale Maps, Closures oder ungelöschte Event-Listener) auf sie zeigen.",[714,2370,2372],{"id":2371},"a-der-unbegrenzte-standard-cache-von-discordjs","A. Der unbegrenzte Standard-Cache von Discord.js",[22,2374,2375,2376,2379],{},"In der Standardkonfiguration legt ",[97,2377,2378],{},"discord.js"," fast jedes empfangene Event im internen Cache ab:",[40,2381,2382,2388,2394],{},[43,2383,2384,2385,1300],{},"Jede empfangene Nachricht (",[97,2386,2387],{},"client.channels.cache.get(id).messages",[43,2389,2390,2391,1300],{},"Jeder Server-Benutzer (",[97,2392,2393],{},"guild.members.cache",[43,2395,2396],{},"Jeder Voice-State und jede Präsenz-Aktualisierung",[22,2398,2399],{},"Auf Servern mit 50.000 Mitgliedern führt dies schnell dazu, dass Hunderttausende User- und Message-Objekte im RAM gehalten werden, selbst wenn sie nie wieder benötigt werden.",[714,2401,2403],{"id":2402},"b-akkumulierte-event-listener-in-modulen","B. Akkumulierte Event-Listener in Modulen",[22,2405,2406,2407,2410,2411,2414],{},"Ein klassischer Fehler in modularen Bots: Bei jedem Reload eines Befehls oder Moduls wird ",[97,2408,2409],{},"client.on(...)"," erneut aufgerufen, ohne dass der alte Listener via ",[97,2412,2413],{},"client.off(...)"," deregistriert wurde:",[635,2416,2418],{"className":1071,"code":2417,"language":1073,"meta":7,"style":7},"\u002F\u002F GEFÄHRLICH: Erzeugt bei jedem Modul-Reload einen neuen Listener im Heap\nexport function initTicketWatcher(client: Client) {\n  client.on('messageCreate', (message) => {\n    handleTicketMessage(message);\n  });\n}\n",[97,2419,2420,2425,2448,2481,2494,2503],{"__ignoreMap":7},[114,2421,2422],{"class":644,"line":552},[114,2423,2424],{"class":1142},"\u002F\u002F GEFÄHRLICH: Erzeugt bei jedem Modul-Reload einen neuen Listener im Heap\n",[114,2426,2427,2429,2431,2434,2436,2439,2441,2444,2446],{"class":644,"line":537},[114,2428,1152],{"class":1080},[114,2430,1232],{"class":1107},[114,2432,2433],{"class":1235}," initTicketWatcher",[114,2435,1239],{"class":735},[114,2437,2438],{"class":1242},"client",[114,2440,1170],{"class":735},[114,2442,2443],{"class":647}," Client",[114,2445,1300],{"class":735},[114,2447,1161],{"class":735},[114,2449,2450,2453,2455,2458,2460,2462,2465,2467,2469,2471,2474,2476,2479],{"class":644,"line":763},[114,2451,2452],{"class":745},"  client",[114,2454,50],{"class":735},[114,2456,2457],{"class":1235},"on",[114,2459,1239],{"class":1166},[114,2461,1095],{"class":735},[114,2463,2464],{"class":651},"messageCreate",[114,2466,1095],{"class":735},[114,2468,1250],{"class":735},[114,2470,257],{"class":735},[114,2472,2473],{"class":1242},"message",[114,2475,1300],{"class":735},[114,2477,2478],{"class":1107}," =>",[114,2480,1161],{"class":735},[114,2482,2483,2486,2488,2490,2492],{"class":644,"line":802},[114,2484,2485],{"class":1235},"    handleTicketMessage",[114,2487,1239],{"class":1166},[114,2489,2473],{"class":745},[114,2491,1300],{"class":1166},[114,2493,1098],{"class":735},[114,2495,2496,2499,2501],{"class":644,"line":808},[114,2497,2498],{"class":735},"  }",[114,2500,1300],{"class":1166},[114,2502,1098],{"class":735},[114,2504,2505],{"class":644,"line":814},[114,2506,879],{"class":735},[29,2508],{},[32,2510,2512],{"id":2511},"_2-v8-heap-snapshots-zur-ursachenanalyse-erstellen","2. V8 Heap-Snapshots zur Ursachenanalyse erstellen",[22,2514,2515,2516,2519],{},"Um herauszufinden, welche Objekte den Heap blockieren, erstellen wir programmatisch Heap-Dumps mit dem nativen ",[97,2517,2518],{},"v8","-Modul von Node.js:",[635,2521,2523],{"className":1071,"code":2522,"language":1073,"meta":7,"style":7},"import v8 from 'node:v8';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport function takeHeapSnapshot(label: string = 'leak-audit'): string {\n  const memUsage = process.memoryUsage();\n  console.log(`[Heap Profiler] RSS: ${(memUsage.rss \u002F 1024 \u002F 1024).toFixed(2)} MB, Heap: ${(memUsage.heapUsed \u002F 1024 \u002F 1024).toFixed(2)} MB`);\n\n  const filename = path.join(process.cwd(), `heap-${label}-${Date.now()}.heapsnapshot`);\n  const snapshotStream = v8.getHeapSnapshot();\n  const fileStream = fs.createWriteStream(filename);\n\n  snapshotStream.pipe(fileStream);\n\n  fileStream.on('finish', () => {\n    console.log(`[Heap Profiler] Snapshot erfolgreich gespeichert: ${filename}`);\n  });\n\n  return filename;\n}\n",[97,2524,2525,2543,2561,2579,2583,2616,2637,2737,2741,2810,2831,2857,2861,2880,2884,2911,2938,2946,2950,2958],{"__ignoreMap":7},[114,2526,2527,2529,2532,2534,2536,2539,2541],{"class":644,"line":552},[114,2528,1081],{"class":1080},[114,2530,2531],{"class":745}," v8 ",[114,2533,1087],{"class":1080},[114,2535,1090],{"class":735},[114,2537,2538],{"class":651},"node:v8",[114,2540,1095],{"class":735},[114,2542,1098],{"class":735},[114,2544,2545,2547,2550,2552,2554,2557,2559],{"class":644,"line":537},[114,2546,1081],{"class":1080},[114,2548,2549],{"class":745}," fs ",[114,2551,1087],{"class":1080},[114,2553,1090],{"class":735},[114,2555,2556],{"class":651},"node:fs",[114,2558,1095],{"class":735},[114,2560,1098],{"class":735},[114,2562,2563,2565,2568,2570,2572,2575,2577],{"class":644,"line":763},[114,2564,1081],{"class":1080},[114,2566,2567],{"class":745}," path ",[114,2569,1087],{"class":1080},[114,2571,1090],{"class":735},[114,2573,2574],{"class":651},"node:path",[114,2576,1095],{"class":735},[114,2578,1098],{"class":735},[114,2580,2581],{"class":644,"line":802},[114,2582,856],{"emptyLinePlaceholder":551},[114,2584,2585,2587,2589,2592,2594,2597,2599,2601,2603,2605,2608,2610,2612,2614],{"class":644,"line":808},[114,2586,1152],{"class":1080},[114,2588,1232],{"class":1107},[114,2590,2591],{"class":1235}," takeHeapSnapshot",[114,2593,1239],{"class":735},[114,2595,2596],{"class":1242},"label",[114,2598,1170],{"class":735},[114,2600,1173],{"class":647},[114,2602,1276],{"class":735},[114,2604,1090],{"class":735},[114,2606,2607],{"class":651},"leak-audit",[114,2609,1095],{"class":735},[114,2611,1260],{"class":735},[114,2613,1173],{"class":647},[114,2615,1161],{"class":735},[114,2617,2618,2620,2623,2625,2628,2630,2633,2635],{"class":644,"line":814},[114,2619,1270],{"class":1107},[114,2621,2622],{"class":745}," memUsage",[114,2624,1276],{"class":735},[114,2626,2627],{"class":745}," process",[114,2629,50],{"class":735},[114,2631,2632],{"class":1235},"memoryUsage",[114,2634,1532],{"class":1166},[114,2636,1098],{"class":735},[114,2638,2639,2642,2644,2647,2649,2652,2655,2658,2661,2663,2666,2669,2672,2675,2677,2679,2681,2684,2686,2689,2691,2694,2697,2699,2701,2703,2706,2708,2710,2712,2714,2716,2718,2720,2722,2724,2726,2728,2731,2733,2735],{"class":644,"line":820},[114,2640,2641],{"class":745},"  console",[114,2643,50],{"class":735},[114,2645,2646],{"class":1235},"log",[114,2648,1239],{"class":1166},[114,2650,2651],{"class":735},"`",[114,2653,2654],{"class":651},"[Heap Profiler] RSS: ",[114,2656,2657],{"class":735},"${",[114,2659,2660],{"class":745},"(memUsage",[114,2662,50],{"class":735},[114,2664,2665],{"class":745},"rss ",[114,2667,2668],{"class":735},"\u002F",[114,2670,2671],{"class":1135}," 1024",[114,2673,2674],{"class":735}," \u002F",[114,2676,2671],{"class":1135},[114,2678,1300],{"class":745},[114,2680,50],{"class":735},[114,2682,2683],{"class":1235},"toFixed",[114,2685,1239],{"class":745},[114,2687,2688],{"class":1135},"2",[114,2690,1300],{"class":745},[114,2692,2693],{"class":735},"}",[114,2695,2696],{"class":651}," MB, Heap: ",[114,2698,2657],{"class":735},[114,2700,2660],{"class":745},[114,2702,50],{"class":735},[114,2704,2705],{"class":745},"heapUsed ",[114,2707,2668],{"class":735},[114,2709,2671],{"class":1135},[114,2711,2674],{"class":735},[114,2713,2671],{"class":1135},[114,2715,1300],{"class":745},[114,2717,50],{"class":735},[114,2719,2683],{"class":1235},[114,2721,1239],{"class":745},[114,2723,2688],{"class":1135},[114,2725,1300],{"class":745},[114,2727,2693],{"class":735},[114,2729,2730],{"class":651}," MB",[114,2732,2651],{"class":735},[114,2734,1300],{"class":1166},[114,2736,1098],{"class":735},[114,2738,2739],{"class":644,"line":826},[114,2740,856],{"emptyLinePlaceholder":551},[114,2742,2743,2745,2748,2750,2753,2755,2758,2760,2763,2765,2768,2770,2772,2775,2778,2780,2782,2784,2787,2789,2792,2794,2797,2799,2801,2804,2806,2808],{"class":644,"line":832},[114,2744,1270],{"class":1107},[114,2746,2747],{"class":745}," filename",[114,2749,1276],{"class":735},[114,2751,2752],{"class":745}," path",[114,2754,50],{"class":735},[114,2756,2757],{"class":1235},"join",[114,2759,1239],{"class":1166},[114,2761,2762],{"class":745},"process",[114,2764,50],{"class":735},[114,2766,2767],{"class":1235},"cwd",[114,2769,1532],{"class":1166},[114,2771,1250],{"class":735},[114,2773,2774],{"class":735}," `",[114,2776,2777],{"class":651},"heap-",[114,2779,2657],{"class":735},[114,2781,2596],{"class":745},[114,2783,2693],{"class":735},[114,2785,2786],{"class":651},"-",[114,2788,2657],{"class":735},[114,2790,2791],{"class":745},"Date",[114,2793,50],{"class":735},[114,2795,2796],{"class":1235},"now",[114,2798,1532],{"class":745},[114,2800,2693],{"class":735},[114,2802,2803],{"class":651},".heapsnapshot",[114,2805,2651],{"class":735},[114,2807,1300],{"class":1166},[114,2809,1098],{"class":735},[114,2811,2812,2814,2817,2819,2822,2824,2827,2829],{"class":644,"line":891},[114,2813,1270],{"class":1107},[114,2815,2816],{"class":745}," snapshotStream",[114,2818,1276],{"class":735},[114,2820,2821],{"class":745}," v8",[114,2823,50],{"class":735},[114,2825,2826],{"class":1235},"getHeapSnapshot",[114,2828,1532],{"class":1166},[114,2830,1098],{"class":735},[114,2832,2833,2835,2838,2840,2843,2845,2848,2850,2853,2855],{"class":644,"line":1204},[114,2834,1270],{"class":1107},[114,2836,2837],{"class":745}," fileStream",[114,2839,1276],{"class":735},[114,2841,2842],{"class":745}," fs",[114,2844,50],{"class":735},[114,2846,2847],{"class":1235},"createWriteStream",[114,2849,1239],{"class":1166},[114,2851,2852],{"class":745},"filename",[114,2854,1300],{"class":1166},[114,2856,1098],{"class":735},[114,2858,2859],{"class":644,"line":1209},[114,2860,856],{"emptyLinePlaceholder":551},[114,2862,2863,2866,2868,2871,2873,2876,2878],{"class":644,"line":1215},[114,2864,2865],{"class":745},"  snapshotStream",[114,2867,50],{"class":735},[114,2869,2870],{"class":1235},"pipe",[114,2872,1239],{"class":1166},[114,2874,2875],{"class":745},"fileStream",[114,2877,1300],{"class":1166},[114,2879,1098],{"class":735},[114,2881,2882],{"class":644,"line":1221},[114,2883,856],{"emptyLinePlaceholder":551},[114,2885,2886,2889,2891,2893,2895,2897,2900,2902,2904,2907,2909],{"class":644,"line":1227},[114,2887,2888],{"class":745},"  fileStream",[114,2890,50],{"class":735},[114,2892,2457],{"class":1235},[114,2894,1239],{"class":1166},[114,2896,1095],{"class":735},[114,2898,2899],{"class":651},"finish",[114,2901,1095],{"class":735},[114,2903,1250],{"class":735},[114,2905,2906],{"class":735}," ()",[114,2908,2478],{"class":1107},[114,2910,1161],{"class":735},[114,2912,2913,2916,2918,2920,2922,2924,2927,2929,2931,2934,2936],{"class":644,"line":1267},[114,2914,2915],{"class":745},"    console",[114,2917,50],{"class":735},[114,2919,2646],{"class":1235},[114,2921,1239],{"class":1166},[114,2923,2651],{"class":735},[114,2925,2926],{"class":651},"[Heap Profiler] Snapshot erfolgreich gespeichert: ",[114,2928,2657],{"class":735},[114,2930,2852],{"class":745},[114,2932,2933],{"class":735},"}`",[114,2935,1300],{"class":1166},[114,2937,1098],{"class":735},[114,2939,2940,2942,2944],{"class":644,"line":1305},[114,2941,2498],{"class":735},[114,2943,1300],{"class":1166},[114,2945,1098],{"class":735},[114,2947,2948],{"class":644,"line":1333},[114,2949,856],{"emptyLinePlaceholder":551},[114,2951,2952,2954,2956],{"class":644,"line":1358},[114,2953,1560],{"class":1080},[114,2955,2747],{"class":745},[114,2957,1098],{"class":735},[114,2959,2960],{"class":644,"line":1363},[114,2961,879],{"class":735},[714,2963,2965],{"id":2964},"auswertung-in-chrome-devtools","Auswertung in Chrome DevTools:",[70,2967,2968,2974,2983,2992,2999],{},[43,2969,2970,2971,50],{},"Öffne im Chrome-Browser ",[97,2972,2973],{},"chrome:\u002F\u002Finspect",[43,2975,103,2976,2979,2980,50],{},[47,2977,2978],{},"\"Open dedicated DevTools for Node\""," oder gehe in den Tab ",[47,2981,2982],{},"Memory",[43,2984,103,2985,2988,2989,2991],{},[47,2986,2987],{},"Load"," und wähle die generierte ",[97,2990,2803],{},"-Datei aus.",[43,2993,2994,2995,2998],{},"Sortiere nach ",[47,2996,2997],{},"Retained Size"," (Speichergröße inklusive aller abhängigen Referenzen).",[43,3000,3001,3002,381,3005,3008,3009,50],{},"Halte Ausschau nach Instanzen von ",[97,3003,3004],{},"Message",[97,3006,3007],{},"GuildMember"," oder ",[97,3010,3011],{},"Closure",[29,3013],{},[32,3015,3017],{"id":3016},"_3-best-practice-benutzerdefinierte-cache-manager-sweeper","3. Best Practice: Benutzerdefinierte Cache-Manager & Sweeper",[22,3019,3020,3021,3023],{},"In modernen Produktionsumgebungen begrenzen wir die Caches von ",[97,3022,2378],{}," rigoros über die Client-Optionen:",[635,3025,3027],{"className":1071,"code":3026,"language":1073,"meta":7,"style":7},"import { Client, GatewayIntentBits, Options } from 'discord.js';\n\nexport const botClient = new Client({\n  intents: [\n    GatewayIntentBits.Guilds,\n    GatewayIntentBits.GuildMessages,\n    GatewayIntentBits.MessageContent,\n  ],\n  makeCache: Options.cacheWithLimits({\n    \u002F\u002F Nachrichten nur bis zu 25 Stück pro Kanal cachen\n    MessageManager: 25,\n    \u002F\u002F Präsenzen und Aktivitäten komplett deaktivieren\n    PresenceManager: 0,\n    \u002F\u002F Reaktionen nicht im Speicher vorhalten\n    ReactionManager: 0,\n    \u002F\u002F User-Profile auf maximale Lebensdauer begrenzen\n    UserManager: {\n      maxSize: 500,\n      keepOverLimit: (value) => value.id === client.user?.id,\n    },\n    \u002F\u002F Voice-States nur für aktive Kanäle\n    VoiceStateManager: 100,\n  }),\n  sweepers: {\n    \u002F\u002F Automatisches Bereinigen alle 30 Minuten\n    ...Options.defaultSweeperSettings,\n    messages: {\n      interval: 1800, \u002F\u002F 30 Minuten\n      lifetime: 900,  \u002F\u002F Nachrichten älter als 15 Minuten entfernen\n    },\n    users: {\n      interval: 3600, \u002F\u002F 1 Stunde\n      filter: () => (user) => !user.bot, \u002F\u002F Nur inaktive Nicht-Bots verwerfen\n    },\n  },\n});\n",[97,3028,3029,3062,3066,3086,3096,3108,3119,3130,3137,3155,3160,3172,3177,3189,3194,3205,3210,3219,3231,3274,3279,3284,3296,3304,3313,3318,3333,3342,3357,3372,3376,3385,3399,3432,3436,3441],{"__ignoreMap":7},[114,3030,3031,3033,3036,3038,3040,3043,3045,3048,3051,3054,3056,3058,3060],{"class":644,"line":552},[114,3032,1081],{"class":1080},[114,3034,3035],{"class":735}," {",[114,3037,2443],{"class":745},[114,3039,1250],{"class":735},[114,3041,3042],{"class":745}," GatewayIntentBits",[114,3044,1250],{"class":735},[114,3046,3047],{"class":745}," Options",[114,3049,3050],{"class":735}," }",[114,3052,3053],{"class":1080}," from",[114,3055,1090],{"class":735},[114,3057,2378],{"class":651},[114,3059,1095],{"class":735},[114,3061,1098],{"class":735},[114,3063,3064],{"class":644,"line":537},[114,3065,856],{"emptyLinePlaceholder":551},[114,3067,3068,3070,3073,3076,3078,3080,3082,3084],{"class":644,"line":763},[114,3069,1152],{"class":1080},[114,3071,3072],{"class":1107}," const",[114,3074,3075],{"class":745}," botClient ",[114,3077,1114],{"class":735},[114,3079,1339],{"class":735},[114,3081,2443],{"class":1235},[114,3083,1239],{"class":745},[114,3085,1330],{"class":735},[114,3087,3088,3091,3093],{"class":644,"line":802},[114,3089,3090],{"class":1166},"  intents",[114,3092,1170],{"class":735},[114,3094,3095],{"class":745}," [\n",[114,3097,3098,3101,3103,3106],{"class":644,"line":808},[114,3099,3100],{"class":745},"    GatewayIntentBits",[114,3102,50],{"class":735},[114,3104,3105],{"class":745},"Guilds",[114,3107,1571],{"class":735},[114,3109,3110,3112,3114,3117],{"class":644,"line":814},[114,3111,3100],{"class":745},[114,3113,50],{"class":735},[114,3115,3116],{"class":745},"GuildMessages",[114,3118,1571],{"class":735},[114,3120,3121,3123,3125,3128],{"class":644,"line":820},[114,3122,3100],{"class":745},[114,3124,50],{"class":735},[114,3126,3127],{"class":745},"MessageContent",[114,3129,1571],{"class":735},[114,3131,3132,3135],{"class":644,"line":826},[114,3133,3134],{"class":745},"  ]",[114,3136,1571],{"class":735},[114,3138,3139,3142,3144,3146,3148,3151,3153],{"class":644,"line":832},[114,3140,3141],{"class":1166},"  makeCache",[114,3143,1170],{"class":735},[114,3145,3047],{"class":745},[114,3147,50],{"class":735},[114,3149,3150],{"class":1235},"cacheWithLimits",[114,3152,1239],{"class":745},[114,3154,1330],{"class":735},[114,3156,3157],{"class":644,"line":891},[114,3158,3159],{"class":1142},"    \u002F\u002F Nachrichten nur bis zu 25 Stück pro Kanal cachen\n",[114,3161,3162,3165,3167,3170],{"class":644,"line":1204},[114,3163,3164],{"class":1166},"    MessageManager",[114,3166,1170],{"class":735},[114,3168,3169],{"class":1135}," 25",[114,3171,1571],{"class":735},[114,3173,3174],{"class":644,"line":1209},[114,3175,3176],{"class":1142},"    \u002F\u002F Präsenzen und Aktivitäten komplett deaktivieren\n",[114,3178,3179,3182,3184,3187],{"class":644,"line":1215},[114,3180,3181],{"class":1166},"    PresenceManager",[114,3183,1170],{"class":735},[114,3185,3186],{"class":1135}," 0",[114,3188,1571],{"class":735},[114,3190,3191],{"class":644,"line":1221},[114,3192,3193],{"class":1142},"    \u002F\u002F Reaktionen nicht im Speicher vorhalten\n",[114,3195,3196,3199,3201,3203],{"class":644,"line":1227},[114,3197,3198],{"class":1166},"    ReactionManager",[114,3200,1170],{"class":735},[114,3202,3186],{"class":1135},[114,3204,1571],{"class":735},[114,3206,3207],{"class":644,"line":1267},[114,3208,3209],{"class":1142},"    \u002F\u002F User-Profile auf maximale Lebensdauer begrenzen\n",[114,3211,3212,3215,3217],{"class":644,"line":1305},[114,3213,3214],{"class":1166},"    UserManager",[114,3216,1170],{"class":735},[114,3218,1161],{"class":735},[114,3220,3221,3224,3226,3229],{"class":644,"line":1333},[114,3222,3223],{"class":1166},"      maxSize",[114,3225,1170],{"class":735},[114,3227,3228],{"class":1135}," 500",[114,3230,1571],{"class":735},[114,3232,3233,3236,3238,3240,3243,3245,3247,3250,3252,3255,3258,3261,3263,3266,3269,3272],{"class":644,"line":1358},[114,3234,3235],{"class":1235},"      keepOverLimit",[114,3237,1170],{"class":735},[114,3239,257],{"class":735},[114,3241,3242],{"class":1242},"value",[114,3244,1300],{"class":735},[114,3246,2478],{"class":1107},[114,3248,3249],{"class":745}," value",[114,3251,50],{"class":735},[114,3253,3254],{"class":745},"id ",[114,3256,3257],{"class":735},"===",[114,3259,3260],{"class":745}," client",[114,3262,50],{"class":735},[114,3264,3265],{"class":745},"user",[114,3267,3268],{"class":735},"?.",[114,3270,3271],{"class":745},"id",[114,3273,1571],{"class":735},[114,3275,3276],{"class":644,"line":1363},[114,3277,3278],{"class":735},"    },\n",[114,3280,3281],{"class":644,"line":1368},[114,3282,3283],{"class":1142},"    \u002F\u002F Voice-States nur für aktive Kanäle\n",[114,3285,3286,3289,3291,3294],{"class":644,"line":1374},[114,3287,3288],{"class":1166},"    VoiceStateManager",[114,3290,1170],{"class":735},[114,3292,3293],{"class":1135}," 100",[114,3295,1571],{"class":735},[114,3297,3298,3300,3302],{"class":644,"line":1401},[114,3299,2498],{"class":735},[114,3301,1300],{"class":745},[114,3303,1571],{"class":735},[114,3305,3306,3309,3311],{"class":644,"line":1435},[114,3307,3308],{"class":1166},"  sweepers",[114,3310,1170],{"class":735},[114,3312,1161],{"class":735},[114,3314,3315],{"class":644,"line":1440},[114,3316,3317],{"class":1142},"    \u002F\u002F Automatisches Bereinigen alle 30 Minuten\n",[114,3319,3320,3323,3326,3328,3331],{"class":644,"line":1483},[114,3321,3322],{"class":735},"    ...",[114,3324,3325],{"class":745},"Options",[114,3327,50],{"class":735},[114,3329,3330],{"class":745},"defaultSweeperSettings",[114,3332,1571],{"class":735},[114,3334,3335,3338,3340],{"class":644,"line":1510},[114,3336,3337],{"class":1166},"    messages",[114,3339,1170],{"class":735},[114,3341,1161],{"class":735},[114,3343,3344,3347,3349,3352,3354],{"class":644,"line":1515},[114,3345,3346],{"class":1166},"      interval",[114,3348,1170],{"class":735},[114,3350,3351],{"class":1135}," 1800",[114,3353,1250],{"class":735},[114,3355,3356],{"class":1142}," \u002F\u002F 30 Minuten\n",[114,3358,3359,3362,3364,3367,3369],{"class":644,"line":1552},[114,3360,3361],{"class":1166},"      lifetime",[114,3363,1170],{"class":735},[114,3365,3366],{"class":1135}," 900",[114,3368,1250],{"class":735},[114,3370,3371],{"class":1142},"  \u002F\u002F Nachrichten älter als 15 Minuten entfernen\n",[114,3373,3374],{"class":644,"line":1557},[114,3375,3278],{"class":735},[114,3377,3378,3381,3383],{"class":644,"line":1565},[114,3379,3380],{"class":1166},"    users",[114,3382,1170],{"class":735},[114,3384,1161],{"class":735},[114,3386,3387,3389,3391,3394,3396],{"class":644,"line":1574},[114,3388,3346],{"class":1166},[114,3390,1170],{"class":735},[114,3392,3393],{"class":1135}," 3600",[114,3395,1250],{"class":735},[114,3397,3398],{"class":1142}," \u002F\u002F 1 Stunde\n",[114,3400,3401,3404,3406,3408,3410,3412,3414,3416,3418,3421,3423,3425,3427,3429],{"class":644,"line":1600},[114,3402,3403],{"class":1235},"      filter",[114,3405,1170],{"class":735},[114,3407,2906],{"class":735},[114,3409,2478],{"class":1107},[114,3411,257],{"class":735},[114,3413,3265],{"class":1242},[114,3415,1300],{"class":735},[114,3417,2478],{"class":1107},[114,3419,3420],{"class":735}," !",[114,3422,3265],{"class":745},[114,3424,50],{"class":735},[114,3426,348],{"class":745},[114,3428,1250],{"class":735},[114,3430,3431],{"class":1142}," \u002F\u002F Nur inaktive Nicht-Bots verwerfen\n",[114,3433,3434],{"class":644,"line":1608},[114,3435,3278],{"class":735},[114,3437,3438],{"class":644,"line":1614},[114,3439,3440],{"class":735},"  },\n",[114,3442,3443,3445,3447],{"class":644,"line":1619},[114,3444,2693],{"class":735},[114,3446,1300],{"class":745},[114,3448,1098],{"class":735},[29,3450],{},[32,3452,3454],{"id":3453},"_4-schwache-referenzen-mit-weakmap-und-weakset","4. Schwache Referenzen mit WeakMap und WeakSet",[22,3456,3457,3458,3461,3462,3465],{},"Wenn dein Bot temporäre Metadaten zu Nachrichten oder Interaktionen speichern muss, nutze ",[97,3459,3460],{},"WeakMap"," anstelle von regulären ",[97,3463,3464],{},"Map","-Objekten:",[635,3467,3469],{"className":1071,"code":3468,"language":1073,"meta":7,"style":7},"\u002F\u002F RICHTIG: Der Garbage Collector kann Message-Objekte abräumen,\n\u002F\u002F sobald sie von discord.js verworfen werden!\nexport const userCooldowns = new WeakMap\u003CMessage, number>();\n\nexport function registerCooldown(message: Message, durationMs: number) {\n  userCooldowns.set(message, Date.now() + durationMs);\n}\n",[97,3470,3471,3476,3481,3514,3518,3549,3583],{"__ignoreMap":7},[114,3472,3473],{"class":644,"line":552},[114,3474,3475],{"class":1142},"\u002F\u002F RICHTIG: Der Garbage Collector kann Message-Objekte abräumen,\n",[114,3477,3478],{"class":644,"line":537},[114,3479,3480],{"class":1142},"\u002F\u002F sobald sie von discord.js verworfen werden!\n",[114,3482,3483,3485,3487,3490,3492,3494,3497,3500,3502,3504,3507,3510,3512],{"class":644,"line":763},[114,3484,1152],{"class":1080},[114,3486,3072],{"class":1107},[114,3488,3489],{"class":745}," userCooldowns ",[114,3491,1114],{"class":735},[114,3493,1339],{"class":735},[114,3495,3496],{"class":1235}," WeakMap",[114,3498,3499],{"class":735},"\u003C",[114,3501,3004],{"class":647},[114,3503,1250],{"class":735},[114,3505,3506],{"class":647}," number",[114,3508,3509],{"class":735},">",[114,3511,1532],{"class":745},[114,3513,1098],{"class":735},[114,3515,3516],{"class":644,"line":802},[114,3517,856],{"emptyLinePlaceholder":551},[114,3519,3520,3522,3524,3527,3529,3531,3533,3536,3538,3541,3543,3545,3547],{"class":644,"line":808},[114,3521,1152],{"class":1080},[114,3523,1232],{"class":1107},[114,3525,3526],{"class":1235}," registerCooldown",[114,3528,1239],{"class":735},[114,3530,2473],{"class":1242},[114,3532,1170],{"class":735},[114,3534,3535],{"class":647}," Message",[114,3537,1250],{"class":735},[114,3539,3540],{"class":1242}," durationMs",[114,3542,1170],{"class":735},[114,3544,3506],{"class":647},[114,3546,1300],{"class":735},[114,3548,1161],{"class":735},[114,3550,3551,3554,3556,3559,3561,3563,3565,3568,3570,3572,3575,3577,3579,3581],{"class":644,"line":814},[114,3552,3553],{"class":745},"  userCooldowns",[114,3555,50],{"class":735},[114,3557,3558],{"class":1235},"set",[114,3560,1239],{"class":1166},[114,3562,2473],{"class":745},[114,3564,1250],{"class":735},[114,3566,3567],{"class":745}," Date",[114,3569,50],{"class":735},[114,3571,2796],{"class":1235},[114,3573,3574],{"class":1166},"() ",[114,3576,260],{"class":735},[114,3578,3540],{"class":745},[114,3580,1300],{"class":1166},[114,3582,1098],{"class":735},[114,3584,3585],{"class":644,"line":820},[114,3586,879],{"class":735},[22,3588,3589,3590,3592],{},"Mit ",[97,3591,3460],{}," verhindert der Key nicht, dass das Originalobjekt freigegeben wird. Sobald der Message-Cache geleert wird, verschwindet der Eintrag automatisch aus dem Speicher.",[29,3594],{},[32,3596,3598],{"id":3597},"_5-zusammenfassung-checkliste-für-247-uptime","5. Zusammenfassung & Checkliste für 24\u002F7 Uptime",[447,3600,3601,3614],{},[450,3602,3603],{},[453,3604,3605,3608,3611],{},[456,3606,3607],{},"Maßnahme",[456,3609,3610],{},"Empfohlener Wert",[456,3612,3613],{},"Wirkung",[467,3615,3616,3630,3641,3652,3667],{},[453,3617,3618,3624,3627],{},[472,3619,3620,3623],{},[97,3621,3622],{},"MessageManager"," Cache-Limit",[472,3625,3626],{},"10–50 pro Kanal",[472,3628,3629],{},"Verhindert lineares RAM-Wachstum bei Chat-Aktivität",[453,3631,3632,3635,3638],{},[472,3633,3634],{},"Message Sweeper Intervall",[472,3636,3637],{},"1800 s (30 Min)",[472,3639,3640],{},"Entfernt alte Nachrichten zuverlässig aus dem Heap",[453,3642,3643,3646,3649],{},[472,3644,3645],{},"Presence Cache",[472,3647,3648],{},"0 (Deaktiviert)",[472,3650,3651],{},"Spart bis zu 70 % Speicher auf großen Community-Servern",[453,3653,3654,3657,3664],{},[472,3655,3656],{},"Event-Listener Deregistrierung",[472,3658,3659,3660,3663],{},"Immer ",[97,3661,3662],{},"client.off()"," bei Modul-Reload",[472,3665,3666],{},"Verhindert Closure-Leaks im Root-Scope",[453,3668,3669,3672,3677],{},[472,3670,3671],{},"V8 Heap Limit",[472,3673,3674],{},[97,3675,3676],{},"--max-old-space-size=512",[472,3678,3679],{},"Zwingt Node.js zu früherer Garbage Collection",[944,3681,3682],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":7,"searchDepth":537,"depth":537,"links":3684},[3685,3689,3692,3693,3694],{"id":2364,"depth":537,"text":2365,"children":3686},[3687,3688],{"id":2371,"depth":763,"text":2372},{"id":2402,"depth":763,"text":2403},{"id":2511,"depth":537,"text":2512,"children":3690},[3691],{"id":2964,"depth":763,"text":2965},{"id":3016,"depth":537,"text":3017},{"id":3453,"depth":537,"text":3454},{"id":3597,"depth":537,"text":3598},"Discord-Bots, die auf großen Servern betrieben werden oder über Wochen ohne Neustart laufen, leiden häufig unter schleichendem RAM-Wachstum. Ein Bot, der nach dem Start 120 MB Arbeitsspeicher belegt, kann innerhalb weniger Tage mehrere Gigabyte verbrauchen, bis die Node.js-Runtime den Prozess mit einem FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory beendet.",{},"\u002Fdocs\u002Fde\u002Fdiscord-memory-leaks",{"title":3699,"description":3695},{"Discord":3700,"description":3702,"category":3703,"order":552,"author":2000,"readTime":3704,"lastUpdated":2002},{"js Memory Leaks beheben":3701},"V8 Heap-Analyse & Cache-Strategien","Praxisleitfaden zur Erkennung und Behebung von Speicherlecks in 24\u002F7 Discord-Bots mit Node.js, V8 Heap-Snapshots und optimiertem Cache-Sweeping.","engineering","12 min","docs\u002Fde\u002Fdiscord-memory-leaks","9OzYllcPtf4hcndxf_irIltNqeOO3ES3yg_WrlwIeXo",{"id":3708,"title":969,"author":12,"body":3709,"category":12,"description":5159,"extension":549,"lastUpdated":12,"meta":5160,"navigation":551,"order":962,"path":5161,"readTime":12,"seo":5162,"stem":5167,"__hash__":5168},"docs\u002Fdocs\u002Fde\u002Fdiscord-sharding-ratelimits.md",{"type":14,"value":3710,"toc":5150},[3711,3715,3722,3725,3727,3731,3734,3737,3740,3746,3748,3752,3759,4308,4326,4328,4332,4338,4724,4726,4730,4733,4759,4763,4766,5117,5119,5123,5147],[17,3712,3714],{"id":3713},"discord-gateway-v10-sharding-rate-limiting-architektur-ab-2500-servern","Discord Gateway v10 Sharding & Rate Limiting: Architektur ab 2.500 Servern",[22,3716,3717,3718,3721],{},"Sobald ein Discord-Bot auf mehr als 2.500 Servern (Guilds) aktiv ist, erzwingt Discord zwingend das sogenannte ",[47,3719,3720],{},"Gateway Sharding",". Ohne Sharding verweigert das Discord Gateway Verbindungsanfragen. Doch auch unterhalb dieser Grenze ist Sharding die wichtigste Architekturmaßnahme zur Vermeidung von CPU-Bottlenecks, Gateway-Disconnects und globalen Rate-Limits.",[22,3723,3724],{},"In diesem Leitfaden betrachten wir die mathematischen Grundlagen des Shardings, die Funktionsweise von Discord v10 Rate-Limit-Buckets und den Aufbau eines stabilen Sharding-Managers.",[29,3726],{},[32,3728,3730],{"id":3729},"_1-wie-discord-gateway-sharding-funktioniert","1. Wie Discord Gateway Sharding funktioniert",[22,3732,3733],{},"Ein Shard ist eine eigenständige WebSocket-Verbindung zum Discord Gateway. Discord weist jeden Server anhand einer deterministischen mathematischen Formel einem spezifischen Shard zu:",[22,3735,3736],{},"$$\\text{shard_id} = (\\text{guild_id} \\gg 22) \\pmod{\\text{total_shards}}$$",[22,3738,3739],{},"Dadurch ist garantiert, dass Events für einen bestimmten Server immer auf genau demselben Shard empfangen werden.",[635,3741,3744],{"className":3742,"code":3743,"language":1053},[1051],"                    ┌─────────────────────────┐\n                    │  Discord Gateway (v10)  │\n                    └────────────┬────────────┘\n         ┌───────────────────────┼───────────────────────┐\n         ▼                       ▼                       ▼\n   ┌───────────┐           ┌───────────┐           ┌───────────┐\n   │  Shard 0  │           │  Shard 1  │           │  Shard 2  │\n   │ Guilds %3 │           │ Guilds %3 │           │ Guilds %3 │\n   └─────┬─────┘           └─────┬─────┘           └─────┬─────┘\n         │                       │                       │\n         └───────────────────────┼───────────────────────┘\n                                 ▼\n                    ┌─────────────────────────┐\n                    │  KiroCloud Worker Pool  │\n                    └─────────────────────────┘\n",[97,3745,3743],{"__ignoreMap":7},[29,3747],{},[32,3749,3751],{"id":3750},"_2-implementierung-mit-dem-shardingmanager","2. Implementierung mit dem ShardingManager",[22,3753,3754,3755,3758],{},"In Node.js starten wir Shards über den ",[97,3756,3757],{},"ShardingManager",", der jeden Shard in einem separaten Node.js-Prozess oder Worker-Thread ausführt:",[635,3760,3762],{"className":1071,"code":3761,"language":1073,"meta":7,"style":7},"\u002F\u002F bot-cluster.ts\nimport { ShardingManager } from 'discord.js';\nimport path from 'node:path';\n\nconst manager = new ShardingManager(path.join(__dirname, 'bot-worker.ts'), {\n  token: process.env.DISCORD_BOT_TOKEN,\n  totalShards: 'auto', \u002F\u002F Discord empfiehlt automatisch die ideale Anzahl\n  respawn: true,        \u002F\u002F Automatischer Neustart bei Prozessabsturz\n  mode: 'worker',       \u002F\u002F 'worker' (Threads) oder 'process' (Child Processes)\n});\n\nmanager.on('shardCreate', (shard) => {\n  console.log(`[Cluster] Shard #${shard.id} initialisiert und gestartet.`);\n\n  shard.on('disconnect', () => {\n    console.warn(`[Cluster] Shard #${shard.id} Verbindung verloren.`);\n  });\n\n  shard.on('reconnecting', () => {\n    console.log(`[Cluster] Shard #${shard.id} verbindet erneut...`);\n  });\n});\n\nmanager.spawn({\n  amount: 'auto',\n  delay: 5500, \u002F\u002F WICHTIG: Mindestens 5,5 Sekunden Pause zwischen Shard-Spawns (Discord Rate-Limit)\n  timeout: 30000,\n}).then(() => {\n  console.log('[Cluster] Alle Shards erfolgreich mit Discord Gateway verbunden.');\n}).catch((err) => {\n  console.error('[Cluster] Kritischer Fehler beim Spawnen der Shards:', err);\n});\n",[97,3763,3764,3769,3790,3806,3810,3848,3869,3888,3904,3923,3931,3935,3966,4000,4004,4030,4064,4072,4076,4101,4134,4142,4150,4154,4167,4182,4197,4209,4228,4249,4273,4300],{"__ignoreMap":7},[114,3765,3766],{"class":644,"line":552},[114,3767,3768],{"class":1142},"\u002F\u002F bot-cluster.ts\n",[114,3770,3771,3773,3775,3778,3780,3782,3784,3786,3788],{"class":644,"line":537},[114,3772,1081],{"class":1080},[114,3774,3035],{"class":735},[114,3776,3777],{"class":745}," ShardingManager",[114,3779,3050],{"class":735},[114,3781,3053],{"class":1080},[114,3783,1090],{"class":735},[114,3785,2378],{"class":651},[114,3787,1095],{"class":735},[114,3789,1098],{"class":735},[114,3791,3792,3794,3796,3798,3800,3802,3804],{"class":644,"line":763},[114,3793,1081],{"class":1080},[114,3795,2567],{"class":745},[114,3797,1087],{"class":1080},[114,3799,1090],{"class":735},[114,3801,2574],{"class":651},[114,3803,1095],{"class":735},[114,3805,1098],{"class":735},[114,3807,3808],{"class":644,"line":802},[114,3809,856],{"emptyLinePlaceholder":551},[114,3811,3812,3814,3817,3819,3821,3823,3826,3828,3830,3833,3835,3837,3840,3842,3844,3846],{"class":644,"line":808},[114,3813,1108],{"class":1107},[114,3815,3816],{"class":745}," manager ",[114,3818,1114],{"class":735},[114,3820,1339],{"class":735},[114,3822,3777],{"class":1235},[114,3824,3825],{"class":745},"(path",[114,3827,50],{"class":735},[114,3829,2757],{"class":1235},[114,3831,3832],{"class":745},"(__dirname",[114,3834,1250],{"class":735},[114,3836,1090],{"class":735},[114,3838,3839],{"class":651},"bot-worker.ts",[114,3841,1095],{"class":735},[114,3843,1300],{"class":745},[114,3845,1250],{"class":735},[114,3847,1161],{"class":735},[114,3849,3850,3853,3855,3857,3859,3862,3864,3867],{"class":644,"line":814},[114,3851,3852],{"class":1166},"  token",[114,3854,1170],{"class":735},[114,3856,2627],{"class":745},[114,3858,50],{"class":735},[114,3860,3861],{"class":745},"env",[114,3863,50],{"class":735},[114,3865,3866],{"class":745},"DISCORD_BOT_TOKEN",[114,3868,1571],{"class":735},[114,3870,3871,3874,3876,3878,3881,3883,3885],{"class":644,"line":820},[114,3872,3873],{"class":1166},"  totalShards",[114,3875,1170],{"class":735},[114,3877,1090],{"class":735},[114,3879,3880],{"class":651},"auto",[114,3882,1095],{"class":735},[114,3884,1250],{"class":735},[114,3886,3887],{"class":1142}," \u002F\u002F Discord empfiehlt automatisch die ideale Anzahl\n",[114,3889,3890,3893,3895,3899,3901],{"class":644,"line":826},[114,3891,3892],{"class":1166},"  respawn",[114,3894,1170],{"class":735},[114,3896,3898],{"class":3897},"sfNiH"," true",[114,3900,1250],{"class":735},[114,3902,3903],{"class":1142},"        \u002F\u002F Automatischer Neustart bei Prozessabsturz\n",[114,3905,3906,3909,3911,3913,3916,3918,3920],{"class":644,"line":832},[114,3907,3908],{"class":1166},"  mode",[114,3910,1170],{"class":735},[114,3912,1090],{"class":735},[114,3914,3915],{"class":651},"worker",[114,3917,1095],{"class":735},[114,3919,1250],{"class":735},[114,3921,3922],{"class":1142},"       \u002F\u002F 'worker' (Threads) oder 'process' (Child Processes)\n",[114,3924,3925,3927,3929],{"class":644,"line":891},[114,3926,2693],{"class":735},[114,3928,1300],{"class":745},[114,3930,1098],{"class":735},[114,3932,3933],{"class":644,"line":1204},[114,3934,856],{"emptyLinePlaceholder":551},[114,3936,3937,3940,3942,3944,3946,3948,3951,3953,3955,3957,3960,3962,3964],{"class":644,"line":1209},[114,3938,3939],{"class":745},"manager",[114,3941,50],{"class":735},[114,3943,2457],{"class":1235},[114,3945,1239],{"class":745},[114,3947,1095],{"class":735},[114,3949,3950],{"class":651},"shardCreate",[114,3952,1095],{"class":735},[114,3954,1250],{"class":735},[114,3956,257],{"class":735},[114,3958,3959],{"class":1242},"shard",[114,3961,1300],{"class":735},[114,3963,2478],{"class":1107},[114,3965,1161],{"class":735},[114,3967,3968,3970,3972,3974,3976,3978,3981,3983,3985,3987,3989,3991,3994,3996,3998],{"class":644,"line":1215},[114,3969,2641],{"class":745},[114,3971,50],{"class":735},[114,3973,2646],{"class":1235},[114,3975,1239],{"class":1166},[114,3977,2651],{"class":735},[114,3979,3980],{"class":651},"[Cluster] Shard #",[114,3982,2657],{"class":735},[114,3984,3959],{"class":745},[114,3986,50],{"class":735},[114,3988,3271],{"class":745},[114,3990,2693],{"class":735},[114,3992,3993],{"class":651}," initialisiert und gestartet.",[114,3995,2651],{"class":735},[114,3997,1300],{"class":1166},[114,3999,1098],{"class":735},[114,4001,4002],{"class":644,"line":1221},[114,4003,856],{"emptyLinePlaceholder":551},[114,4005,4006,4009,4011,4013,4015,4017,4020,4022,4024,4026,4028],{"class":644,"line":1227},[114,4007,4008],{"class":745},"  shard",[114,4010,50],{"class":735},[114,4012,2457],{"class":1235},[114,4014,1239],{"class":1166},[114,4016,1095],{"class":735},[114,4018,4019],{"class":651},"disconnect",[114,4021,1095],{"class":735},[114,4023,1250],{"class":735},[114,4025,2906],{"class":735},[114,4027,2478],{"class":1107},[114,4029,1161],{"class":735},[114,4031,4032,4034,4036,4039,4041,4043,4045,4047,4049,4051,4053,4055,4058,4060,4062],{"class":644,"line":1267},[114,4033,2915],{"class":745},[114,4035,50],{"class":735},[114,4037,4038],{"class":1235},"warn",[114,4040,1239],{"class":1166},[114,4042,2651],{"class":735},[114,4044,3980],{"class":651},[114,4046,2657],{"class":735},[114,4048,3959],{"class":745},[114,4050,50],{"class":735},[114,4052,3271],{"class":745},[114,4054,2693],{"class":735},[114,4056,4057],{"class":651}," Verbindung verloren.",[114,4059,2651],{"class":735},[114,4061,1300],{"class":1166},[114,4063,1098],{"class":735},[114,4065,4066,4068,4070],{"class":644,"line":1305},[114,4067,2498],{"class":735},[114,4069,1300],{"class":1166},[114,4071,1098],{"class":735},[114,4073,4074],{"class":644,"line":1333},[114,4075,856],{"emptyLinePlaceholder":551},[114,4077,4078,4080,4082,4084,4086,4088,4091,4093,4095,4097,4099],{"class":644,"line":1358},[114,4079,4008],{"class":745},[114,4081,50],{"class":735},[114,4083,2457],{"class":1235},[114,4085,1239],{"class":1166},[114,4087,1095],{"class":735},[114,4089,4090],{"class":651},"reconnecting",[114,4092,1095],{"class":735},[114,4094,1250],{"class":735},[114,4096,2906],{"class":735},[114,4098,2478],{"class":1107},[114,4100,1161],{"class":735},[114,4102,4103,4105,4107,4109,4111,4113,4115,4117,4119,4121,4123,4125,4128,4130,4132],{"class":644,"line":1363},[114,4104,2915],{"class":745},[114,4106,50],{"class":735},[114,4108,2646],{"class":1235},[114,4110,1239],{"class":1166},[114,4112,2651],{"class":735},[114,4114,3980],{"class":651},[114,4116,2657],{"class":735},[114,4118,3959],{"class":745},[114,4120,50],{"class":735},[114,4122,3271],{"class":745},[114,4124,2693],{"class":735},[114,4126,4127],{"class":651}," verbindet erneut...",[114,4129,2651],{"class":735},[114,4131,1300],{"class":1166},[114,4133,1098],{"class":735},[114,4135,4136,4138,4140],{"class":644,"line":1368},[114,4137,2498],{"class":735},[114,4139,1300],{"class":1166},[114,4141,1098],{"class":735},[114,4143,4144,4146,4148],{"class":644,"line":1374},[114,4145,2693],{"class":735},[114,4147,1300],{"class":745},[114,4149,1098],{"class":735},[114,4151,4152],{"class":644,"line":1401},[114,4153,856],{"emptyLinePlaceholder":551},[114,4155,4156,4158,4160,4163,4165],{"class":644,"line":1435},[114,4157,3939],{"class":745},[114,4159,50],{"class":735},[114,4161,4162],{"class":1235},"spawn",[114,4164,1239],{"class":745},[114,4166,1330],{"class":735},[114,4168,4169,4172,4174,4176,4178,4180],{"class":644,"line":1440},[114,4170,4171],{"class":1166},"  amount",[114,4173,1170],{"class":735},[114,4175,1090],{"class":735},[114,4177,3880],{"class":651},[114,4179,1095],{"class":735},[114,4181,1571],{"class":735},[114,4183,4184,4187,4189,4192,4194],{"class":644,"line":1483},[114,4185,4186],{"class":1166},"  delay",[114,4188,1170],{"class":735},[114,4190,4191],{"class":1135}," 5500",[114,4193,1250],{"class":735},[114,4195,4196],{"class":1142}," \u002F\u002F WICHTIG: Mindestens 5,5 Sekunden Pause zwischen Shard-Spawns (Discord Rate-Limit)\n",[114,4198,4199,4202,4204,4207],{"class":644,"line":1510},[114,4200,4201],{"class":1166},"  timeout",[114,4203,1170],{"class":735},[114,4205,4206],{"class":1135}," 30000",[114,4208,1571],{"class":735},[114,4210,4211,4213,4215,4217,4220,4222,4224,4226],{"class":644,"line":1515},[114,4212,2693],{"class":735},[114,4214,1300],{"class":745},[114,4216,50],{"class":735},[114,4218,4219],{"class":1235},"then",[114,4221,1239],{"class":745},[114,4223,1532],{"class":735},[114,4225,2478],{"class":1107},[114,4227,1161],{"class":735},[114,4229,4230,4232,4234,4236,4238,4240,4243,4245,4247],{"class":644,"line":1552},[114,4231,2641],{"class":745},[114,4233,50],{"class":735},[114,4235,2646],{"class":1235},[114,4237,1239],{"class":1166},[114,4239,1095],{"class":735},[114,4241,4242],{"class":651},"[Cluster] Alle Shards erfolgreich mit Discord Gateway verbunden.",[114,4244,1095],{"class":735},[114,4246,1300],{"class":1166},[114,4248,1098],{"class":735},[114,4250,4251,4253,4255,4257,4260,4262,4264,4267,4269,4271],{"class":644,"line":1557},[114,4252,2693],{"class":735},[114,4254,1300],{"class":745},[114,4256,50],{"class":735},[114,4258,4259],{"class":1235},"catch",[114,4261,1239],{"class":745},[114,4263,1239],{"class":735},[114,4265,4266],{"class":1242},"err",[114,4268,1300],{"class":735},[114,4270,2478],{"class":1107},[114,4272,1161],{"class":735},[114,4274,4275,4277,4279,4282,4284,4286,4289,4291,4293,4296,4298],{"class":644,"line":1565},[114,4276,2641],{"class":745},[114,4278,50],{"class":735},[114,4280,4281],{"class":1235},"error",[114,4283,1239],{"class":1166},[114,4285,1095],{"class":735},[114,4287,4288],{"class":651},"[Cluster] Kritischer Fehler beim Spawnen der Shards:",[114,4290,1095],{"class":735},[114,4292,1250],{"class":735},[114,4294,4295],{"class":745}," err",[114,4297,1300],{"class":1166},[114,4299,1098],{"class":735},[114,4301,4302,4304,4306],{"class":644,"line":1574},[114,4303,2693],{"class":735},[114,4305,1300],{"class":745},[114,4307,1098],{"class":735},[109,4309,4310],{},[22,4311,4312,4314,4317,4318,4321,4322,4325],{},[114,4313,181],{},[47,4315,4316],{},"Das Identify-Rate-Limit:"," Discord erlaubt nur 1 Gateway-Identify alle 5 Sekunden pro Shard-Block (",[97,4319,4320],{},"max_concurrency","). Ein zu schneller Spawn führt zum temporären IP-Ban (HTTP 429). Setze den ",[97,4323,4324],{},"delay","-Parameter daher immer auf mindestens 5.500 ms.",[29,4327],{},[32,4329,4331],{"id":4330},"_3-shard-übergreifende-kommunikation-cross-shard-messaging","3. Shard-übergreifende Kommunikation (Cross-Shard Messaging)",[22,4333,4334,4335,1170],{},"Da jeder Shard in einem isolierten Thread läuft, haben sie keinen gemeinsamen Speicher. Wenn du globale Statistiken (wie die Gesamtanzahl aller Server oder Nutzer) abfragen möchtest, nutzt du ",[97,4336,4337],{},"broadcastEval",[635,4339,4341],{"className":1071,"code":4340,"language":1073,"meta":7,"style":7},"\u002F\u002F Ermittlung der plattformweiten Server- und Nutzerzahlen\nexport async function getPlatformMetrics(manager: ShardingManager) {\n  const results = await manager.broadcastEval((client) => {\n    return {\n      guildCount: client.guilds.cache.size,\n      memberCount: client.guilds.cache.reduce((acc, g) => acc + g.memberCount, 0),\n      ping: client.ws.ping,\n    };\n  });\n\n  const totalGuilds = results.reduce((acc, cur) => acc + cur.guildCount, 0);\n  const totalMembers = results.reduce((acc, cur) => acc + cur.memberCount, 0);\n  const avgPing = Math.round(results.reduce((acc, cur) => acc + cur.ping, 0) \u002F results.length);\n\n  return { totalGuilds, totalMembers, avgPing };\n}\n",[97,4342,4343,4348,4372,4403,4410,4436,4495,4516,4521,4529,4533,4582,4629,4697,4701,4720],{"__ignoreMap":7},[114,4344,4345],{"class":644,"line":552},[114,4346,4347],{"class":1142},"\u002F\u002F Ermittlung der plattformweiten Server- und Nutzerzahlen\n",[114,4349,4350,4352,4355,4357,4360,4362,4364,4366,4368,4370],{"class":644,"line":537},[114,4351,1152],{"class":1080},[114,4353,4354],{"class":1107}," async",[114,4356,1232],{"class":1107},[114,4358,4359],{"class":1235}," getPlatformMetrics",[114,4361,1239],{"class":735},[114,4363,3939],{"class":1242},[114,4365,1170],{"class":735},[114,4367,3777],{"class":647},[114,4369,1300],{"class":735},[114,4371,1161],{"class":735},[114,4373,4374,4376,4379,4381,4384,4387,4389,4391,4393,4395,4397,4399,4401],{"class":644,"line":763},[114,4375,1270],{"class":1107},[114,4377,4378],{"class":745}," results",[114,4380,1276],{"class":735},[114,4382,4383],{"class":1080}," await",[114,4385,4386],{"class":745}," manager",[114,4388,50],{"class":735},[114,4390,4337],{"class":1235},[114,4392,1239],{"class":1166},[114,4394,1239],{"class":735},[114,4396,2438],{"class":1242},[114,4398,1300],{"class":735},[114,4400,2478],{"class":1107},[114,4402,1161],{"class":735},[114,4404,4405,4408],{"class":644,"line":802},[114,4406,4407],{"class":1080},"    return",[114,4409,1161],{"class":735},[114,4411,4412,4415,4417,4419,4421,4424,4426,4429,4431,4434],{"class":644,"line":808},[114,4413,4414],{"class":1166},"      guildCount",[114,4416,1170],{"class":735},[114,4418,3260],{"class":745},[114,4420,50],{"class":735},[114,4422,4423],{"class":745},"guilds",[114,4425,50],{"class":735},[114,4427,4428],{"class":745},"cache",[114,4430,50],{"class":735},[114,4432,4433],{"class":745},"size",[114,4435,1571],{"class":735},[114,4437,4438,4441,4443,4445,4447,4449,4451,4453,4455,4458,4460,4462,4465,4467,4470,4472,4474,4477,4480,4482,4484,4487,4489,4491,4493],{"class":644,"line":814},[114,4439,4440],{"class":1166},"      memberCount",[114,4442,1170],{"class":735},[114,4444,3260],{"class":745},[114,4446,50],{"class":735},[114,4448,4423],{"class":745},[114,4450,50],{"class":735},[114,4452,4428],{"class":745},[114,4454,50],{"class":735},[114,4456,4457],{"class":1235},"reduce",[114,4459,1239],{"class":1166},[114,4461,1239],{"class":735},[114,4463,4464],{"class":1242},"acc",[114,4466,1250],{"class":735},[114,4468,4469],{"class":1242}," g",[114,4471,1300],{"class":735},[114,4473,2478],{"class":1107},[114,4475,4476],{"class":745}," acc",[114,4478,4479],{"class":735}," +",[114,4481,4469],{"class":745},[114,4483,50],{"class":735},[114,4485,4486],{"class":745},"memberCount",[114,4488,1250],{"class":735},[114,4490,3186],{"class":1135},[114,4492,1300],{"class":1166},[114,4494,1571],{"class":735},[114,4496,4497,4500,4502,4504,4506,4509,4511,4514],{"class":644,"line":820},[114,4498,4499],{"class":1166},"      ping",[114,4501,1170],{"class":735},[114,4503,3260],{"class":745},[114,4505,50],{"class":735},[114,4507,4508],{"class":745},"ws",[114,4510,50],{"class":735},[114,4512,4513],{"class":745},"ping",[114,4515,1571],{"class":735},[114,4517,4518],{"class":644,"line":826},[114,4519,4520],{"class":735},"    };\n",[114,4522,4523,4525,4527],{"class":644,"line":832},[114,4524,2498],{"class":735},[114,4526,1300],{"class":1166},[114,4528,1098],{"class":735},[114,4530,4531],{"class":644,"line":891},[114,4532,856],{"emptyLinePlaceholder":551},[114,4534,4535,4537,4540,4542,4544,4546,4548,4550,4552,4554,4556,4559,4561,4563,4565,4567,4569,4571,4574,4576,4578,4580],{"class":644,"line":1204},[114,4536,1270],{"class":1107},[114,4538,4539],{"class":745}," totalGuilds",[114,4541,1276],{"class":735},[114,4543,4378],{"class":745},[114,4545,50],{"class":735},[114,4547,4457],{"class":1235},[114,4549,1239],{"class":1166},[114,4551,1239],{"class":735},[114,4553,4464],{"class":1242},[114,4555,1250],{"class":735},[114,4557,4558],{"class":1242}," cur",[114,4560,1300],{"class":735},[114,4562,2478],{"class":1107},[114,4564,4476],{"class":745},[114,4566,4479],{"class":735},[114,4568,4558],{"class":745},[114,4570,50],{"class":735},[114,4572,4573],{"class":745},"guildCount",[114,4575,1250],{"class":735},[114,4577,3186],{"class":1135},[114,4579,1300],{"class":1166},[114,4581,1098],{"class":735},[114,4583,4584,4586,4589,4591,4593,4595,4597,4599,4601,4603,4605,4607,4609,4611,4613,4615,4617,4619,4621,4623,4625,4627],{"class":644,"line":1209},[114,4585,1270],{"class":1107},[114,4587,4588],{"class":745}," totalMembers",[114,4590,1276],{"class":735},[114,4592,4378],{"class":745},[114,4594,50],{"class":735},[114,4596,4457],{"class":1235},[114,4598,1239],{"class":1166},[114,4600,1239],{"class":735},[114,4602,4464],{"class":1242},[114,4604,1250],{"class":735},[114,4606,4558],{"class":1242},[114,4608,1300],{"class":735},[114,4610,2478],{"class":1107},[114,4612,4476],{"class":745},[114,4614,4479],{"class":735},[114,4616,4558],{"class":745},[114,4618,50],{"class":735},[114,4620,4486],{"class":745},[114,4622,1250],{"class":735},[114,4624,3186],{"class":1135},[114,4626,1300],{"class":1166},[114,4628,1098],{"class":735},[114,4630,4631,4633,4636,4638,4641,4643,4646,4648,4651,4653,4655,4657,4659,4661,4663,4665,4667,4669,4671,4673,4675,4677,4679,4681,4683,4685,4687,4689,4691,4693,4695],{"class":644,"line":1215},[114,4632,1270],{"class":1107},[114,4634,4635],{"class":745}," avgPing",[114,4637,1276],{"class":735},[114,4639,4640],{"class":745}," Math",[114,4642,50],{"class":735},[114,4644,4645],{"class":1235},"round",[114,4647,1239],{"class":1166},[114,4649,4650],{"class":745},"results",[114,4652,50],{"class":735},[114,4654,4457],{"class":1235},[114,4656,1239],{"class":1166},[114,4658,1239],{"class":735},[114,4660,4464],{"class":1242},[114,4662,1250],{"class":735},[114,4664,4558],{"class":1242},[114,4666,1300],{"class":735},[114,4668,2478],{"class":1107},[114,4670,4476],{"class":745},[114,4672,4479],{"class":735},[114,4674,4558],{"class":745},[114,4676,50],{"class":735},[114,4678,4513],{"class":745},[114,4680,1250],{"class":735},[114,4682,3186],{"class":1135},[114,4684,1327],{"class":1166},[114,4686,2668],{"class":735},[114,4688,4378],{"class":745},[114,4690,50],{"class":735},[114,4692,1318],{"class":745},[114,4694,1300],{"class":1166},[114,4696,1098],{"class":735},[114,4698,4699],{"class":644,"line":1221},[114,4700,856],{"emptyLinePlaceholder":551},[114,4702,4703,4705,4707,4709,4711,4713,4715,4717],{"class":644,"line":1227},[114,4704,1560],{"class":1080},[114,4706,3035],{"class":735},[114,4708,4539],{"class":745},[114,4710,1250],{"class":735},[114,4712,4588],{"class":745},[114,4714,1250],{"class":735},[114,4716,4635],{"class":745},[114,4718,4719],{"class":735}," };\n",[114,4721,4722],{"class":644,"line":1267},[114,4723,879],{"class":735},[29,4725],{},[32,4727,4729],{"id":4728},"_4-discord-rest-rate-limit-buckets-meistern","4. Discord REST Rate-Limit Buckets meistern",[22,4731,4732],{},"Discord unterscheidet strikt zwischen Gateway-Limits (WebSockets) und REST-API-Limits (HTTP). Die REST-API nutzt ein Bucket-System, das über HTTP-Response-Header gesteuert wird:",[40,4734,4735,4741,4747,4753],{},[43,4736,4737,4740],{},[97,4738,4739],{},"X-RateLimit-Limit",": Maximale Anzahl an Anfragen im aktuellen Zeitfenster.",[43,4742,4743,4746],{},[97,4744,4745],{},"X-RateLimit-Remaining",": Verbleibende Anfragen.",[43,4748,4749,4752],{},[97,4750,4751],{},"X-RateLimit-Reset-After",": Sekunden bis zum Reset des Buckets.",[43,4754,4755,4758],{},[97,4756,4757],{},"X-RateLimit-Bucket",": Eindeutiger Hash des betroffenen Endpunkts.",[714,4760,4762],{"id":4761},"best-practice-für-rest-queues","Best Practice für REST-Queues:",[22,4764,4765],{},"Wenn dein Bot Massen-Operationen ausführt (z. B. Rollen-Zuweisung an 500 Nutzer), nutze eine sequentielle Queue mit dynamischem Backoff:",[635,4767,4769],{"className":1071,"code":4768,"language":1073,"meta":7,"style":7},"export async function executeWithRateLimitRetry\u003CT>(fn: () => Promise\u003CT>, maxRetries = 3): Promise\u003CT> {\n  let attempt = 0;\n  while (attempt \u003C maxRetries) {\n    try {\n      return await fn();\n    } catch (error: any) {\n      if (error?.status === 429) {\n        const retryAfter = (error.rawError?.retry_after ?? 1) * 1000;\n        console.warn(`[RateLimit 429] Warte ${retryAfter}ms vor erneutem Versuch...`);\n        await new Promise((resolve) => setTimeout(resolve, retryAfter + 100));\n        attempt++;\n      } else {\n        throw error;\n      }\n    }\n  }\n  throw new Error(`Max retries (${maxRetries}) erreicht.`);\n}\n",[97,4770,4771,4829,4842,4861,4868,4882,4903,4927,4967,4999,5039,5047,5057,5067,5072,5077,5081,5113],{"__ignoreMap":7},[114,4772,4773,4775,4777,4779,4782,4784,4787,4790,4793,4795,4797,4799,4802,4804,4806,4809,4812,4814,4817,4819,4821,4823,4825,4827],{"class":644,"line":552},[114,4774,1152],{"class":1080},[114,4776,4354],{"class":1107},[114,4778,1232],{"class":1107},[114,4780,4781],{"class":1235}," executeWithRateLimitRetry",[114,4783,3499],{"class":735},[114,4785,4786],{"class":647},"T",[114,4788,4789],{"class":735},">(",[114,4791,4792],{"class":1235},"fn",[114,4794,1170],{"class":735},[114,4796,2906],{"class":735},[114,4798,2478],{"class":1107},[114,4800,4801],{"class":647}," Promise",[114,4803,3499],{"class":735},[114,4805,4786],{"class":647},[114,4807,4808],{"class":735},">,",[114,4810,4811],{"class":1242}," maxRetries",[114,4813,1276],{"class":735},[114,4815,4816],{"class":1135}," 3",[114,4818,1260],{"class":735},[114,4820,4801],{"class":647},[114,4822,3499],{"class":735},[114,4824,4786],{"class":647},[114,4826,3509],{"class":735},[114,4828,1161],{"class":735},[114,4830,4831,4833,4836,4838,4840],{"class":644,"line":537},[114,4832,1443],{"class":1107},[114,4834,4835],{"class":745}," attempt",[114,4837,1276],{"class":735},[114,4839,3186],{"class":1135},[114,4841,1098],{"class":735},[114,4843,4844,4847,4849,4852,4855,4857,4859],{"class":644,"line":763},[114,4845,4846],{"class":1080},"  while",[114,4848,257],{"class":1166},[114,4850,4851],{"class":745},"attempt",[114,4853,4854],{"class":735}," \u003C",[114,4856,4811],{"class":745},[114,4858,1327],{"class":1166},[114,4860,1330],{"class":735},[114,4862,4863,4866],{"class":644,"line":802},[114,4864,4865],{"class":1080},"    try",[114,4867,1161],{"class":735},[114,4869,4870,4873,4875,4878,4880],{"class":644,"line":808},[114,4871,4872],{"class":1080},"      return",[114,4874,4383],{"class":1080},[114,4876,4877],{"class":1235}," fn",[114,4879,1532],{"class":1166},[114,4881,1098],{"class":735},[114,4883,4884,4887,4890,4892,4894,4896,4899,4901],{"class":644,"line":814},[114,4885,4886],{"class":735},"    }",[114,4888,4889],{"class":1080}," catch",[114,4891,257],{"class":735},[114,4893,4281],{"class":1242},[114,4895,1170],{"class":735},[114,4897,4898],{"class":647}," any",[114,4900,1300],{"class":735},[114,4902,1161],{"class":735},[114,4904,4905,4908,4910,4912,4914,4917,4920,4923,4925],{"class":644,"line":820},[114,4906,4907],{"class":1080},"      if",[114,4909,257],{"class":1166},[114,4911,4281],{"class":745},[114,4913,3268],{"class":735},[114,4915,4916],{"class":745},"status",[114,4918,4919],{"class":735}," ===",[114,4921,4922],{"class":1135}," 429",[114,4924,1327],{"class":1166},[114,4926,1330],{"class":735},[114,4928,4929,4932,4935,4937,4939,4941,4943,4946,4948,4951,4954,4957,4959,4962,4965],{"class":644,"line":826},[114,4930,4931],{"class":1107},"        const",[114,4933,4934],{"class":745}," retryAfter",[114,4936,1276],{"class":735},[114,4938,257],{"class":1166},[114,4940,4281],{"class":745},[114,4942,50],{"class":735},[114,4944,4945],{"class":745},"rawError",[114,4947,3268],{"class":735},[114,4949,4950],{"class":745},"retry_after",[114,4952,4953],{"class":735}," ??",[114,4955,4956],{"class":1135}," 1",[114,4958,1327],{"class":1166},[114,4960,4961],{"class":735},"*",[114,4963,4964],{"class":1135}," 1000",[114,4966,1098],{"class":735},[114,4968,4969,4972,4974,4976,4978,4980,4983,4985,4988,4990,4993,4995,4997],{"class":644,"line":832},[114,4970,4971],{"class":745},"        console",[114,4973,50],{"class":735},[114,4975,4038],{"class":1235},[114,4977,1239],{"class":1166},[114,4979,2651],{"class":735},[114,4981,4982],{"class":651},"[RateLimit 429] Warte ",[114,4984,2657],{"class":735},[114,4986,4987],{"class":745},"retryAfter",[114,4989,2693],{"class":735},[114,4991,4992],{"class":651},"ms vor erneutem Versuch...",[114,4994,2651],{"class":735},[114,4996,1300],{"class":1166},[114,4998,1098],{"class":735},[114,5000,5001,5004,5006,5008,5010,5012,5015,5017,5019,5022,5024,5026,5028,5030,5032,5034,5037],{"class":644,"line":891},[114,5002,5003],{"class":1080},"        await",[114,5005,1339],{"class":735},[114,5007,4801],{"class":647},[114,5009,1239],{"class":1166},[114,5011,1239],{"class":735},[114,5013,5014],{"class":1242},"resolve",[114,5016,1300],{"class":735},[114,5018,2478],{"class":1107},[114,5020,5021],{"class":1235}," setTimeout",[114,5023,1239],{"class":1166},[114,5025,5014],{"class":745},[114,5027,1250],{"class":735},[114,5029,4934],{"class":745},[114,5031,4479],{"class":735},[114,5033,3293],{"class":1135},[114,5035,5036],{"class":1166},"))",[114,5038,1098],{"class":735},[114,5040,5041,5044],{"class":644,"line":1204},[114,5042,5043],{"class":745},"        attempt",[114,5045,5046],{"class":735},"++;\n",[114,5048,5049,5052,5055],{"class":644,"line":1209},[114,5050,5051],{"class":735},"      }",[114,5053,5054],{"class":1080}," else",[114,5056,1161],{"class":735},[114,5058,5059,5062,5065],{"class":644,"line":1215},[114,5060,5061],{"class":1080},"        throw",[114,5063,5064],{"class":745}," error",[114,5066,1098],{"class":735},[114,5068,5069],{"class":644,"line":1221},[114,5070,5071],{"class":735},"      }\n",[114,5073,5074],{"class":644,"line":1227},[114,5075,5076],{"class":735},"    }\n",[114,5078,5079],{"class":644,"line":1267},[114,5080,817],{"class":735},[114,5082,5083,5086,5088,5090,5092,5094,5097,5099,5102,5104,5107,5109,5111],{"class":644,"line":1305},[114,5084,5085],{"class":1080},"  throw",[114,5087,1339],{"class":735},[114,5089,1342],{"class":1235},[114,5091,1239],{"class":1166},[114,5093,2651],{"class":735},[114,5095,5096],{"class":651},"Max retries (",[114,5098,2657],{"class":735},[114,5100,5101],{"class":745},"maxRetries",[114,5103,2693],{"class":735},[114,5105,5106],{"class":651},") erreicht.",[114,5108,2651],{"class":735},[114,5110,1300],{"class":1166},[114,5112,1098],{"class":735},[114,5114,5115],{"class":644,"line":1333},[114,5116,879],{"class":735},[29,5118],{},[32,5120,5122],{"id":5121},"_5-faustregeln-für-die-cluster-dimensionierung","5. Faustregeln für die Cluster-Dimensionierung",[70,5124,5125,5131,5137],{},[43,5126,5127,5130],{},[47,5128,5129],{},"Faustregel für Shard-Anzahl:"," Plane ca. 1.000 Server pro Shard ein (obwohl Discord bis zu 2.500 erlaubt). Ein Bot mit 4.000 Servern läuft mit 4–5 Shards deutlich stabiler als mit der Minimalanzahl von 2.",[43,5132,5133,5136],{},[47,5134,5135],{},"CPU-Thread-Allokation:"," Teile Worker-Threads so auf, dass nicht mehr als 2 Shards auf demselben physischen CPU-Kern um Event-Loop-Zyklen konkurrieren.",[43,5138,5139,5142,5143,5146],{},[47,5140,5141],{},"Automatisierte Überwachung:"," Auf KiroCloud wird die Gateway-Latenz (",[97,5144,5145],{},"ws.ping",") im Sekundentakt gemessen. Bei Latenzsprüngen über 250 ms sollte ein automatisierter Reconnect eingeleitet werden.",[944,5148,5149],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":7,"searchDepth":537,"depth":537,"links":5151},[5152,5153,5154,5155,5158],{"id":3729,"depth":537,"text":3730},{"id":3750,"depth":537,"text":3751},{"id":4330,"depth":537,"text":4331},{"id":4728,"depth":537,"text":4729,"children":5156},[5157],{"id":4761,"depth":763,"text":4762},{"id":5121,"depth":537,"text":5122},"Sobald ein Discord-Bot auf mehr als 2.500 Servern (Guilds) aktiv ist, erzwingt Discord zwingend das sogenannte Gateway Sharding. Ohne Sharding verweigert das Discord Gateway Verbindungsanfragen. Doch auch unterhalb dieser Grenze ist Sharding die wichtigste Architekturmaßnahme zur Vermeidung von CPU-Bottlenecks, Gateway-Disconnects und globalen Rate-Limits.",{},"\u002Fdocs\u002Fde\u002Fdiscord-sharding-ratelimits",{"title":5163,"description":5159},{"Discord Gateway v10 Sharding & Rate Limiting":5164,"description":5165,"category":3703,"order":537,"author":2000,"readTime":5166,"lastUpdated":2002},"Architektur ab 2.500 Servern","Technischer Leitfaden zur Skalierung von Discord-Bots über 2.500 Server. Gateway Sharding, Bucket Rate Limits und verteilte Worker-Architektur.","14 min","docs\u002Fde\u002Fdiscord-sharding-ratelimits","n4NhAHgmlxn5UOIyaHYrLEMIwG7WnnvrLKdYT9KToFY",{"id":5170,"title":5171,"author":12,"body":5172,"category":547,"description":5479,"extension":549,"lastUpdated":12,"meta":5480,"navigation":551,"order":552,"path":5481,"readTime":12,"seo":5482,"stem":5483,"__hash__":5484},"docs\u002Fdocs\u002Fde\u002Findex.md","Einführung",{"type":14,"value":5173,"toc":5466},[5174,5178,5183,5187,5190,5210,5214,5217,5221,5224,5228,5231,5257,5261,5264,5278,5282,5285,5296,5300,5303,5389,5393,5419,5423,5426,5452,5454,5463],[17,5175,5177],{"id":5176},"einführung-in-kirocloud","Einführung in KiroCloud",[22,5179,5180,5182],{},[47,5181,4],{}," ist eine dedizierte Hosting-Plattform für Discord-Bots, Minecraft-Server und Community-Tools. Jede Bot-Instanz läuft in einer isolierten Prozess-Umgebung mit fest zugewiesenen CPU- und Arbeitsspeicher-Ressourcen.",[32,5184,5186],{"id":5185},"architektur-und-zielsetzung","Architektur und Zielsetzung",[22,5188,5189],{},"Die Plattform stellt Entwicklern und Administratoren Werkzeuge für Skalierbarkeit, Echtzeit-Monitoring und standardisierte API-Schnittstellen bereit:",[40,5191,5192,5198,5204],{},[43,5193,5194,5197],{},[47,5195,5196],{},"Entwickler-Fokus:"," Moderne Web-Architektur (Nuxt 4, Vue 3, Drizzle ORM) mit typisierten Endpunkten und direkter CLI-\u002FAPI-Kontrolle.",[43,5199,5200,5203],{},[47,5201,5202],{},"Transparenz und Metriken:"," Sekundengenaues Monitoring für RAM-, CPU- und Event-Dispatch-Auslastung.",[43,5205,5206,5209],{},[47,5207,5208],{},"Sicherheits-Architektur:"," Token-Envelope-Verschlüsselung mit AES-256-GCM, HMAC-Integritätsprüfungen und granulare Rate-Limits.",[32,5211,5213],{"id":5212},"kernkomponenten","Kernkomponenten",[22,5215,5216],{},"KiroCloud kombiniert Bot-Laufzeitumgebungen, Telemetrie und Server-Administration.",[714,5218,5220],{"id":5219},"_1-dedizierte-ressourcen-zuteilung","1. Dedizierte Ressourcen-Zuteilung",[22,5222,5223],{},"Jeder Bot läuft in seiner eigenen isolierten Umgebung. Ein fehlerhafter Code in einem anderen Bot kann deinen Bot niemals beeinträchtigen. Dies wird durch strikte Containerisierung und Ressourcen-Limits sichergestellt.",[714,5225,5227],{"id":5226},"_2-modulares-plug-play-system","2. Modulares Plug & Play System",[22,5229,5230],{},"Aktiviere nur die Funktionen, die du für deinen Server benötigst:",[40,5232,5233,5239,5245,5251],{},[43,5234,5235,5238],{},[47,5236,5237],{},"Willkommensnachrichten:"," Personalisiere den Eintritt neuer Mitglieder.",[43,5240,5241,5244],{},[47,5242,5243],{},"Ticket-System:"," Professioneller Support direkt in Discord.",[43,5246,5247,5250],{},[47,5248,5249],{},"Moderations-Tools:"," Automatisierte Filter für Spam und unangebrachte Inhalte.",[43,5252,5253,5256],{},[47,5254,5255],{},"Level-System:"," Belohne Aktivität mit XP und Rollen.",[714,5258,5260],{"id":5259},"_3-echtzeit-monitoring-telemetrie","3. Echtzeit-Monitoring & Telemetrie",[22,5262,5263],{},"Über WebSockets streamt das Backend kontinuierlich Performance-Metriken an das Frontend.",[40,5265,5266,5269,5272,5275],{},[43,5267,5268],{},"CPU-Auslastung in Prozent",[43,5270,5271],{},"Speichernutzung (RAM) in Megabyte",[43,5273,5274],{},"Netzwerk-Latenz (Ping zur Discord API)",[43,5276,5277],{},"Uptime-Tracking und automatische Neustarts bei Abstürzen",[714,5279,5281],{"id":5280},"_4-tiefe-minecraft-integration","4. Tiefe Minecraft-Integration",[22,5283,5284],{},"KiroCloud schlägt eine Brücke zwischen Discord und Minecraft:",[40,5286,5287,5290,5293],{},[43,5288,5289],{},"Synchronisiere Ränge und Rollen zwischen Discord und dem Minecraft-Server.",[43,5291,5292],{},"Sende Befehle via RCON direkt aus dem KiroCloud-Dashboard an den Server.",[43,5294,5295],{},"Verwalte Whitelists, Bans und Spieler-Inventare zentralisiert.",[32,5297,5299],{"id":5298},"architektur-übersicht","Architektur-Übersicht",[22,5301,5302],{},"Das System ist als monolithische Applikation mit Microservice-Eigenschaften (via Nitro) konzipiert, was schnelle Ladezeiten und geringe Latenz bei API-Anfragen ermöglicht.",[635,5304,5308],{"className":5305,"code":5306,"language":5307,"meta":7,"style":7},"language-ascii shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","┌────────────────────────────────┐      ┌──────────────────────────────┐\n│        Benutzer-Browser        │ \u003C──> │        KiroCloud Web         │\n│  (Vue 3, Nuxt UI, Tailwind)    │      │    (SSR, Nuxt 4, Vue Use)    │\n└────────────────────────────────┘      └──────────────┬───────────────┘\n                                                       │\n                                        ┌──────────────┴───────────────┐\n                                        │       Nitro Backend          │\n                                        │ (API, WebSockets, Worker)    │\n                                        └──────────────┬───────────────┘\n                                                       │\n                ┌───────────────────────┬──────────────┴───────┬──────────────────────┐\n                │                       │                      │                      │\n     ┌──────────┴──────────┐   ┌────────┴──────────┐   ┌───────┴──────────┐   ┌───────┴──────────┐\n     │   PostgreSQL 16     │   │     Redis 7       │   │   Discord API    │   │ Minecraft RCON   │\n     │   (Drizzle ORM)     │   │ (Caching, PubSub) │   │ (OAuth2, Bots)   │   │ (Live-Console)   │\n     └─────────────────────┘   └───────────────────┘   └──────────────────┘   └──────────────────┘\n","ascii",[97,5309,5310,5315,5320,5325,5330,5335,5340,5345,5350,5355,5359,5364,5369,5374,5379,5384],{"__ignoreMap":7},[114,5311,5312],{"class":644,"line":552},[114,5313,5314],{},"┌────────────────────────────────┐      ┌──────────────────────────────┐\n",[114,5316,5317],{"class":644,"line":537},[114,5318,5319],{},"│        Benutzer-Browser        │ \u003C──> │        KiroCloud Web         │\n",[114,5321,5322],{"class":644,"line":763},[114,5323,5324],{},"│  (Vue 3, Nuxt UI, Tailwind)    │      │    (SSR, Nuxt 4, Vue Use)    │\n",[114,5326,5327],{"class":644,"line":802},[114,5328,5329],{},"└────────────────────────────────┘      └──────────────┬───────────────┘\n",[114,5331,5332],{"class":644,"line":808},[114,5333,5334],{},"                                                       │\n",[114,5336,5337],{"class":644,"line":814},[114,5338,5339],{},"                                        ┌──────────────┴───────────────┐\n",[114,5341,5342],{"class":644,"line":820},[114,5343,5344],{},"                                        │       Nitro Backend          │\n",[114,5346,5347],{"class":644,"line":826},[114,5348,5349],{},"                                        │ (API, WebSockets, Worker)    │\n",[114,5351,5352],{"class":644,"line":832},[114,5353,5354],{},"                                        └──────────────┬───────────────┘\n",[114,5356,5357],{"class":644,"line":891},[114,5358,5334],{},[114,5360,5361],{"class":644,"line":1204},[114,5362,5363],{},"                ┌───────────────────────┬──────────────┴───────┬──────────────────────┐\n",[114,5365,5366],{"class":644,"line":1209},[114,5367,5368],{},"                │                       │                      │                      │\n",[114,5370,5371],{"class":644,"line":1215},[114,5372,5373],{},"     ┌──────────┴──────────┐   ┌────────┴──────────┐   ┌───────┴──────────┐   ┌───────┴──────────┐\n",[114,5375,5376],{"class":644,"line":1221},[114,5377,5378],{},"     │   PostgreSQL 16     │   │     Redis 7       │   │   Discord API    │   │ Minecraft RCON   │\n",[114,5380,5381],{"class":644,"line":1227},[114,5382,5383],{},"     │   (Drizzle ORM)     │   │ (Caching, PubSub) │   │ (OAuth2, Bots)   │   │ (Live-Console)   │\n",[114,5385,5386],{"class":644,"line":1267},[114,5387,5388],{},"     └─────────────────────┘   └───────────────────┘   └──────────────────┘   └──────────────────┘\n",[714,5390,5392],{"id":5391},"der-technologie-stack","Der Technologie-Stack",[40,5394,5395,5401,5407,5413],{},[43,5396,5397,5400],{},[47,5398,5399],{},"Frontend:"," Nuxt 4, Vue 3 (Composition API), TailwindCSS, Nuxt UI, Lucide Icons.",[43,5402,5403,5406],{},[47,5404,5405],{},"Backend:"," Nitro Server, H3, WebSockets, Zod für Validierung.",[43,5408,5409,5412],{},[47,5410,5411],{},"Datenbank:"," PostgreSQL (gesteuert durch Drizzle ORM) für persistente Daten.",[43,5414,5415,5418],{},[47,5416,5417],{},"Caching & State:"," Redis für Rate-Limiting, Session-Management und Echtzeit-Events.",[32,5420,5422],{"id":5421},"erste-schritte","Erste Schritte",[22,5424,5425],{},"Um mit KiroCloud zu starten, folge diesen einfachen Schritten:",[70,5427,5428,5434,5440,5446],{},[43,5429,5430,5433],{},[47,5431,5432],{},"Authentifizierung:","\nKlicke auf der Startseite auf \"Login\" und melde dich sicher über Discord (OAuth2) an. Wir speichern keine Passwörter von Discord, sondern verifizieren dich über offizielle Tokens.",[43,5435,5436,5439],{},[47,5437,5438],{},"Profil einrichten:","\nErgänze (optional) eine E-Mail-Adresse und richte die Zwei-Faktor-Authentifizierung (2FA) ein, um deinen Account maximal zu schützen.",[43,5441,5442,5445],{},[47,5443,5444],{},"Bot erstellen \u002F verknüpfen:","\nNavigiere zum Dashboard und füge deinen Discord-Bot-Token ein. Unser System validiert den Token sofort und stellt eine sichere Verbindung her.",[43,5447,5448,5451],{},[47,5449,5450],{},"Module konfigurieren:","\nAktiviere die gewünschten Features (z.B. Minecraft-Sync oder Ticket-System) über die grafische Oberfläche. Kein Code erforderlich!",[29,5453],{},[22,5455,5456],{},[292,5457,5458,5459,5462],{},"Nächster Schritt: ",[58,5460,11],{"href":5461},"\u002Fdocs\u002Fadd-bot"," – Erfahre, wie du deinen Discord-Bot erstellst und mit KiroCloud verknüpfst.",[944,5464,5465],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":537,"depth":537,"links":5467},[5468,5469,5475,5478],{"id":5185,"depth":537,"text":5186},{"id":5212,"depth":537,"text":5213,"children":5470},[5471,5472,5473,5474],{"id":5219,"depth":763,"text":5220},{"id":5226,"depth":763,"text":5227},{"id":5259,"depth":763,"text":5260},{"id":5280,"depth":763,"text":5281},{"id":5298,"depth":537,"text":5299,"children":5476},[5477],{"id":5391,"depth":763,"text":5392},{"id":5421,"depth":537,"text":5422},"Willkommen bei KiroCloud - Deiner professionellen Discord-Bot-Infrastruktur.",{},"\u002Fdocs\u002Fde",{"title":5171,"description":5479},"docs\u002Fde\u002Findex","3RYd0AGQKQL1dieRXcGcBrsFpIpMQfgqZhWt6JOE-QU",{"id":5486,"title":5487,"author":2000,"body":5488,"category":6034,"description":6035,"extension":549,"lastUpdated":2002,"meta":6036,"navigation":551,"order":763,"path":6037,"readTime":3704,"seo":6038,"stem":6039,"__hash__":6040},"docs\u002Fdocs\u002Fde\u002Flinux-cgroups-limits.md","Linux Cgroups v2 & Kernel-Limits für Multi-Tenant Bot-Hosting",{"type":14,"value":5489,"toc":6027},[5490,5493,5504,5511,5513,5517,5520,5552,5558,5560,5564,5570,5623,5626,5628,5637,5645,5696,5701,5703,5707,5713,6021,6024],[17,5491,5487],{"id":5492},"linux-cgroups-v2-kernel-limits-für-multi-tenant-bot-hosting",[22,5494,5495,5496,5499,5500,5503],{},"Wenn mehrere Kunden-Bots auf einem gemeinsamen Linux-Server betrieben werden, kann ein fehlerhafter Bot mit einer Endlosschleife (",[97,5497,5498],{},"while(true)",") oder einem Speicherleck die gesamte Maschine lahmlegen. Ohne Kernel-Einschränkungen beansprucht dieser Prozess 100 % aller CPU-Kerne, verdrängt andere Prozesse in die Swap-Partition und führt zum Absturz benachbarter Anwendungen (das klassische ",[292,5501,5502],{},"\"Noisy Neighbor\"","-Problem).",[22,5505,5506,5507,5510],{},"Auf KiroCloud setzen wir auf ",[47,5508,5509],{},"Linux Control Groups (Cgroups v2)"," und systemd Resource Accounting, um jedem Bot-Container exakte Hard- und Soft-Limits für CPU, RAM und I\u002FO zuzuweisen.",[29,5512],{},[32,5514,5516],{"id":5515},"_1-was-sind-cgroups-v2","1. Was sind Cgroups v2?",[22,5518,5519],{},"Cgroups (Control Groups) sind eine Kernel-Funktion von Linux, die es erlaubt, Prozesse in hierarchischen Gruppen zu organisieren und deren Ressourcenverbrauch präzise zu drosseln:",[40,5521,5522,5531,5543],{},[43,5523,5524,5530],{},[47,5525,5526,5527,1260],{},"CPU Controller (",[97,5528,5529],{},"cpu.max"," Bestimmt, wie viel CPU-Zeit ein Prozess pro Zeitfenster nutzen darf.",[43,5532,5533,5542],{},[47,5534,5535,5536,381,5539,1260],{},"Memory Controller (",[97,5537,5538],{},"memory.max",[97,5540,5541],{},"memory.high"," Begrenzt den physikalischen RAM-Verbrauch und steuert den Out-Of-Memory (OOM) Killer.",[43,5544,5545,5551],{},[47,5546,5547,5548,1260],{},"IO Controller (",[97,5549,5550],{},"io.max"," Begrenzt Lese- und Schreiboperationen auf Enterprise-NVMe-SSDs, um I\u002FO-Staus zu verhindern.",[635,5553,5556],{"className":5554,"code":5555,"language":1053},[1051],"                  ┌───────────────────────────────┐\n                  │    Linux Kernel Cgroups v2    │\n                  └───────────────┬───────────────┘\n         ┌────────────────────────┼────────────────────────┐\n         ▼                        ▼                        ▼\n  \u002Fsys\u002Ffs\u002Fcgroup\u002F         \u002Fsys\u002Ffs\u002Fcgroup\u002F          \u002Fsys\u002Ffs\u002Fcgroup\u002F\n  bot-1234\u002F               bot-5678\u002F                bot-9999\u002F\n  ├── cpu.max: 50000      ├── cpu.max: 100000      ├── cpu.max: 200000\n  ├── memory.max: 512M    ├── memory.max: 1024M    ├── memory.max: 2048M\n  └── io.max: 50M\u002Fs       └── io.max: 50M\u002Fs        └── io.max: 100M\u002Fs\n",[97,5557,5555],{"__ignoreMap":7},[29,5559],{},[32,5561,5563],{"id":5562},"_2-cpu-quotas-konfigurieren-keine-100-last-durch-endlosschleifen","2. CPU-Quotas konfigurieren: Keine 100%-Last durch Endlosschleifen",[22,5565,5566,5567,5569],{},"Das CPU-Limit wird in ",[97,5568,5529],{}," als Bruchteil eines Quota-Fensters (Standard: 100.000 Mikrosekunden = 100 ms) definiert:",[635,5571,5573],{"className":637,"code":5572,"language":639,"meta":7,"style":7},"# 50% eines CPU-Kerns: 50.000 Mikrosekunden pro 100.000 Mikrosekunden-Fenster\necho \"50000 100000\" > \u002Fsys\u002Ffs\u002Fcgroup\u002Fkiro-bots\u002Fbot-alpha\u002Fcpu.max\n\n# 1,5 CPU-Kerne:\necho \"150000 100000\" > \u002Fsys\u002Ffs\u002Fcgroup\u002Fkiro-bots\u002Fbot-beta\u002Fcpu.max\n",[97,5574,5575,5580,5598,5602,5607],{"__ignoreMap":7},[114,5576,5577],{"class":644,"line":552},[114,5578,5579],{"class":1142},"# 50% eines CPU-Kerns: 50.000 Mikrosekunden pro 100.000 Mikrosekunden-Fenster\n",[114,5581,5582,5585,5587,5590,5592,5595],{"class":644,"line":537},[114,5583,5584],{"class":1235},"echo",[114,5586,736],{"class":735},[114,5588,5589],{"class":651},"50000 100000",[114,5591,742],{"class":735},[114,5593,5594],{"class":735}," >",[114,5596,5597],{"class":651}," \u002Fsys\u002Ffs\u002Fcgroup\u002Fkiro-bots\u002Fbot-alpha\u002Fcpu.max\n",[114,5599,5600],{"class":644,"line":763},[114,5601,856],{"emptyLinePlaceholder":551},[114,5603,5604],{"class":644,"line":802},[114,5605,5606],{"class":1142},"# 1,5 CPU-Kerne:\n",[114,5608,5609,5611,5613,5616,5618,5620],{"class":644,"line":808},[114,5610,5584],{"class":1235},[114,5612,736],{"class":735},[114,5614,5615],{"class":651},"150000 100000",[114,5617,742],{"class":735},[114,5619,5594],{"class":735},[114,5621,5622],{"class":651}," \u002Fsys\u002Ffs\u002Fcgroup\u002Fkiro-bots\u002Fbot-beta\u002Fcpu.max\n",[22,5624,5625],{},"Wenn ein Bot mehr CPU-Zeit anfordert, als ihm zusteht, drosselt der Linux Completely Fair Scheduler (CFS) den Prozess automatisch, ohne dass andere Bots auf dem Host davon beeinträchtigt werden.",[29,5627],{},[32,5629,5631,5632,5634,5635,1300],{"id":5630},"_3-memory-caps-sanfte-drosselung-memoryhigh-vs-memorymax","3. Memory Caps & Sanfte Drosselung (",[97,5633,5541],{}," vs. ",[97,5636,5538],{},[22,5638,5639,5640,5642,5643,1260],{},"In Cgroups v2 unterscheidet der Kernel zwischen einer sanften Warnschwelle (",[97,5641,5541],{},") und einer harten OOM-Grenze (",[97,5644,5538],{},[635,5646,5648],{"className":637,"code":5647,"language":639,"meta":7,"style":7},"# Sanftes Limit: Ab 450 MB wird der Bot gedrosselt und aggressiv bereinigt\necho \"471859200\" > \u002Fsys\u002Ffs\u002Fcgroup\u002Fkiro-bots\u002Fbot-alpha\u002Fmemory.high\n\n# Hartes Limit (512 MB): Bei Überschreitung greift der OOM-Killer\necho \"536870912\" > \u002Fsys\u002Ffs\u002Fcgroup\u002Fkiro-bots\u002Fbot-alpha\u002Fmemory.max\n",[97,5649,5650,5655,5671,5675,5680],{"__ignoreMap":7},[114,5651,5652],{"class":644,"line":552},[114,5653,5654],{"class":1142},"# Sanftes Limit: Ab 450 MB wird der Bot gedrosselt und aggressiv bereinigt\n",[114,5656,5657,5659,5661,5664,5666,5668],{"class":644,"line":537},[114,5658,5584],{"class":1235},[114,5660,736],{"class":735},[114,5662,5663],{"class":651},"471859200",[114,5665,742],{"class":735},[114,5667,5594],{"class":735},[114,5669,5670],{"class":651}," \u002Fsys\u002Ffs\u002Fcgroup\u002Fkiro-bots\u002Fbot-alpha\u002Fmemory.high\n",[114,5672,5673],{"class":644,"line":763},[114,5674,856],{"emptyLinePlaceholder":551},[114,5676,5677],{"class":644,"line":802},[114,5678,5679],{"class":1142},"# Hartes Limit (512 MB): Bei Überschreitung greift der OOM-Killer\n",[114,5681,5682,5684,5686,5689,5691,5693],{"class":644,"line":808},[114,5683,5584],{"class":1235},[114,5685,736],{"class":735},[114,5687,5688],{"class":651},"536870912",[114,5690,742],{"class":735},[114,5692,5594],{"class":735},[114,5694,5695],{"class":651}," \u002Fsys\u002Ffs\u002Fcgroup\u002Fkiro-bots\u002Fbot-alpha\u002Fmemory.max\n",[22,5697,3589,5698,5700],{},[97,5699,5541],{}," zwingt der Linux-Kernel den Prozess dazu, Page-Caches freizugeben und verlangsamt Speicherallokationen, bevor ein harter Crash eintritt.",[29,5702],{},[32,5704,5706],{"id":5705},"_4-automatisches-management-via-systemd-run-in-nodejs","4. Automatisches Management via systemd-run in Node.js",[22,5708,5709,5710,1170],{},"Anstatt Cgroups manuell im Pseudo-Dateisystem zu beschreiben, nutzt die KiroCloud Bot Engine ",[97,5711,5712],{},"systemd-run",[635,5714,5716],{"className":1071,"code":5715,"language":1073,"meta":7,"style":7},"import { execSync } from 'node:child_process';\n\nexport function startBotWithCgroups(botId: string, scriptPath: string) {\n  const serviceName = `kiro-bot-${botId}`;\n\n  const cmd = [\n    'systemd-run',\n    `--unit=${serviceName}`,\n    '--slice=kiro-bots.slice',\n    '--property=CPUQuota=75%',\n    '--property=MemoryMax=512M',\n    '--property=MemoryHigh=450M',\n    '--property=TasksMax=100', \u002F\u002F Schutz vor Fork-Bomben\n    '--property=Restart=on-failure',\n    'node', scriptPath,\n  ].join(' ');\n\n  execSync(cmd, { stdio: 'inherit' });\n  console.log(`[Cgroups] Bot ${botId} erfolgreich isoliert als ${serviceName} gestartet.`);\n}\n",[97,5717,5718,5740,5744,5775,5797,5801,5812,5823,5840,5851,5862,5873,5884,5898,5909,5924,5942,5946,5978,6017],{"__ignoreMap":7},[114,5719,5720,5722,5724,5727,5729,5731,5733,5736,5738],{"class":644,"line":552},[114,5721,1081],{"class":1080},[114,5723,3035],{"class":735},[114,5725,5726],{"class":745}," execSync",[114,5728,3050],{"class":735},[114,5730,3053],{"class":1080},[114,5732,1090],{"class":735},[114,5734,5735],{"class":651},"node:child_process",[114,5737,1095],{"class":735},[114,5739,1098],{"class":735},[114,5741,5742],{"class":644,"line":537},[114,5743,856],{"emptyLinePlaceholder":551},[114,5745,5746,5748,5750,5753,5755,5758,5760,5762,5764,5767,5769,5771,5773],{"class":644,"line":763},[114,5747,1152],{"class":1080},[114,5749,1232],{"class":1107},[114,5751,5752],{"class":1235}," startBotWithCgroups",[114,5754,1239],{"class":735},[114,5756,5757],{"class":1242},"botId",[114,5759,1170],{"class":735},[114,5761,1173],{"class":647},[114,5763,1250],{"class":735},[114,5765,5766],{"class":1242}," scriptPath",[114,5768,1170],{"class":735},[114,5770,1173],{"class":647},[114,5772,1300],{"class":735},[114,5774,1161],{"class":735},[114,5776,5777,5779,5782,5784,5786,5789,5791,5793,5795],{"class":644,"line":802},[114,5778,1270],{"class":1107},[114,5780,5781],{"class":745}," serviceName",[114,5783,1276],{"class":735},[114,5785,2774],{"class":735},[114,5787,5788],{"class":651},"kiro-bot-",[114,5790,2657],{"class":735},[114,5792,5757],{"class":745},[114,5794,2933],{"class":735},[114,5796,1098],{"class":735},[114,5798,5799],{"class":644,"line":808},[114,5800,856],{"emptyLinePlaceholder":551},[114,5802,5803,5805,5808,5810],{"class":644,"line":814},[114,5804,1270],{"class":1107},[114,5806,5807],{"class":745}," cmd",[114,5809,1276],{"class":735},[114,5811,3095],{"class":1166},[114,5813,5814,5817,5819,5821],{"class":644,"line":820},[114,5815,5816],{"class":735},"    '",[114,5818,5712],{"class":651},[114,5820,1095],{"class":735},[114,5822,1571],{"class":735},[114,5824,5825,5828,5831,5833,5836,5838],{"class":644,"line":826},[114,5826,5827],{"class":735},"    `",[114,5829,5830],{"class":651},"--unit=",[114,5832,2657],{"class":735},[114,5834,5835],{"class":745},"serviceName",[114,5837,2933],{"class":735},[114,5839,1571],{"class":735},[114,5841,5842,5844,5847,5849],{"class":644,"line":832},[114,5843,5816],{"class":735},[114,5845,5846],{"class":651},"--slice=kiro-bots.slice",[114,5848,1095],{"class":735},[114,5850,1571],{"class":735},[114,5852,5853,5855,5858,5860],{"class":644,"line":891},[114,5854,5816],{"class":735},[114,5856,5857],{"class":651},"--property=CPUQuota=75%",[114,5859,1095],{"class":735},[114,5861,1571],{"class":735},[114,5863,5864,5866,5869,5871],{"class":644,"line":1204},[114,5865,5816],{"class":735},[114,5867,5868],{"class":651},"--property=MemoryMax=512M",[114,5870,1095],{"class":735},[114,5872,1571],{"class":735},[114,5874,5875,5877,5880,5882],{"class":644,"line":1209},[114,5876,5816],{"class":735},[114,5878,5879],{"class":651},"--property=MemoryHigh=450M",[114,5881,1095],{"class":735},[114,5883,1571],{"class":735},[114,5885,5886,5888,5891,5893,5895],{"class":644,"line":1215},[114,5887,5816],{"class":735},[114,5889,5890],{"class":651},"--property=TasksMax=100",[114,5892,1095],{"class":735},[114,5894,1250],{"class":735},[114,5896,5897],{"class":1142}," \u002F\u002F Schutz vor Fork-Bomben\n",[114,5899,5900,5902,5905,5907],{"class":644,"line":1221},[114,5901,5816],{"class":735},[114,5903,5904],{"class":651},"--property=Restart=on-failure",[114,5906,1095],{"class":735},[114,5908,1571],{"class":735},[114,5910,5911,5913,5916,5918,5920,5922],{"class":644,"line":1227},[114,5912,5816],{"class":735},[114,5914,5915],{"class":651},"node",[114,5917,1095],{"class":735},[114,5919,1250],{"class":735},[114,5921,5766],{"class":745},[114,5923,1571],{"class":735},[114,5925,5926,5928,5930,5932,5934,5936,5938,5940],{"class":644,"line":1267},[114,5927,3134],{"class":1166},[114,5929,50],{"class":735},[114,5931,2757],{"class":1235},[114,5933,1239],{"class":1166},[114,5935,1095],{"class":735},[114,5937,1090],{"class":735},[114,5939,1300],{"class":1166},[114,5941,1098],{"class":735},[114,5943,5944],{"class":644,"line":1305},[114,5945,856],{"emptyLinePlaceholder":551},[114,5947,5948,5951,5953,5956,5958,5960,5963,5965,5967,5970,5972,5974,5976],{"class":644,"line":1333},[114,5949,5950],{"class":1235},"  execSync",[114,5952,1239],{"class":1166},[114,5954,5955],{"class":745},"cmd",[114,5957,1250],{"class":735},[114,5959,3035],{"class":735},[114,5961,5962],{"class":1166}," stdio",[114,5964,1170],{"class":735},[114,5966,1090],{"class":735},[114,5968,5969],{"class":651},"inherit",[114,5971,1095],{"class":735},[114,5973,3050],{"class":735},[114,5975,1300],{"class":1166},[114,5977,1098],{"class":735},[114,5979,5980,5982,5984,5986,5988,5990,5993,5995,5997,5999,6002,6004,6006,6008,6011,6013,6015],{"class":644,"line":1358},[114,5981,2641],{"class":745},[114,5983,50],{"class":735},[114,5985,2646],{"class":1235},[114,5987,1239],{"class":1166},[114,5989,2651],{"class":735},[114,5991,5992],{"class":651},"[Cgroups] Bot ",[114,5994,2657],{"class":735},[114,5996,5757],{"class":745},[114,5998,2693],{"class":735},[114,6000,6001],{"class":651}," erfolgreich isoliert als ",[114,6003,2657],{"class":735},[114,6005,5835],{"class":745},[114,6007,2693],{"class":735},[114,6009,6010],{"class":651}," gestartet.",[114,6012,2651],{"class":735},[114,6014,1300],{"class":1166},[114,6016,1098],{"class":735},[114,6018,6019],{"class":644,"line":1363},[114,6020,879],{"class":735},[22,6022,6023],{},"Mit dieser Architektur garantieren wir auf KiroCloud maximale Ausfallsicherheit und absolute Fair-Share-Verteilung aller Host-Ressourcen.",[944,6025,6026],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":7,"searchDepth":537,"depth":537,"links":6028},[6029,6030,6031,6033],{"id":5515,"depth":537,"text":5516},{"id":5562,"depth":537,"text":5563},{"id":5630,"depth":537,"text":6032},"3. Memory Caps & Sanfte Drosselung (memory.high vs. memory.max)",{"id":5705,"depth":537,"text":5706},"performance","Leitfaden zur Prozess- und Ressourcenisolation unter Linux. Cgroups v2, CPU Quotas, Memory Caps und Schutz vor Noisy Neighbors in der Cloud.",{},"\u002Fdocs\u002Fde\u002Flinux-cgroups-limits",{"title":5487,"description":6035},"docs\u002Fde\u002Flinux-cgroups-limits","B9U-V5RXHtVsYvTBapzUoyf0Cff3NfzM5soYriUzK8A",{"id":6042,"title":969,"author":12,"body":6043,"category":12,"description":6051,"extension":549,"lastUpdated":12,"meta":6608,"navigation":551,"order":962,"path":6609,"readTime":12,"seo":6610,"stem":6615,"__hash__":6616},"docs\u002Fdocs\u002Fde\u002Fmicroservices-gaming-networks.md",{"type":14,"value":6044,"toc":6602},[6045,6049,6052,6059,6061,6065,6071,6074,6076,6080,6083,6089,6091,6095,6098,6332,6335,6573,6575,6579,6599],[17,6046,6048],{"id":6047},"microservices-vs-monolith-für-gaming-netzwerke-skalierbare-discord-minecraft-cloud","Microservices vs Monolith für Gaming-Netzwerke: Skalierbare Discord & Minecraft Cloud",[22,6050,6051],{},"Kleine Gaming-Communities beginnen meist mit einem monolithischen System: Ein einziger Node.js-Prozess handhabt den Discord-Bot, stellt eine Express-Weboberfläche bereit und greift direkt auf lokale JSON-Dateien oder SQLite zu. Sobald die Community jedoch auf hunderte Spieler und zehntausende Discord-Mitglieder wächst, gerät dieser Aufbau ins Wanken: Ein einziger schwerer Web-Request blockiert den Bot, und ein Bot-Crash reißt das gesamte Dashboard mit in den Abgrund.",[22,6053,6054,6055,6058],{},"In diesem Leitfaden analysieren wir den Übergang vom Monolithen zu einer ",[47,6056,6057],{},"entkoppelten, modularen Microservices-Architektur",", wie sie KiroCloud für High-Traffic-Netzwerke bereitstellt.",[29,6060],{},[32,6062,6064],{"id":6063},"_1-die-grenzen-des-monolithen","1. Die Grenzen des Monolithen",[635,6066,6069],{"className":6067,"code":6068,"language":1053},[1051],"MONOLITH (Nicht resilient):\n┌────────────────────────────────────────────────────────┐\n│               Einziger Node.js Prozess                 │\n│  - Discord Bot Gateway WebSocket                       │\n│  - Web Dashboard REST API (Express)                    │\n│  - Minecraft RCON Socket                               │\n│  - Lokale SQLite Datenbank (Blockiert bei Write-Locks) │\n└────────────────────────────────────────────────────────┘\n  ▲ Crash in einem Teilbereich = Totalausfall für alle!\n",[97,6070,6068],{"__ignoreMap":7},[22,6072,6073],{},"Sobald Web-Traffic (z. B. 200 Spieler öffnen zeitgleich das Dashboard) den Event-Loop blockiert, kann der Discord-Bot keine Heartbeats mehr senden und verliert die Verbindung.",[29,6075],{},[32,6077,6079],{"id":6078},"_2-die-moderne-kirocloud-ziel-architektur","2. Die moderne KiroCloud Ziel-Architektur",[22,6081,6082],{},"In einer resilienten Cloud-Architektur werden alle Komponenten in eigenständige, lose gekoppelte Services zerlegt:",[635,6084,6087],{"className":6085,"code":6086,"language":1053},[1051],"┌─────────────────────────┐          ┌─────────────────────────┐\n│     Discord Gateway     │          │    Web-Browser \u002F User   │\n└────────────┬────────────┘          └────────────┬────────────┘\n             │                                    │\n             ▼                                    ▼\n┌─────────────────────────┐          ┌─────────────────────────┐\n│  Bot Worker Service     │          │   Nuxt 4 Web Plattform  │\n│  (Discord.js \u002F Shards)  │          │   (Server-Side Rendered)│\n└────────────┬────────────┘          └────────────┬────────────┘\n             │                                    │\n             └──────────────┬─────────────────────┘\n                            ▼\n             ┌─────────────────────────────┐\n             │  Zentraler Redis Message    │\n             │  Broker & Event Bus         │\n             └──────────────┬──────────────┘\n                            │\n             ┌──────────────┼─────────────────────┐\n             ▼                                    ▼\n┌─────────────────────────┐          ┌─────────────────────────┐\n│   PostgreSQL Cluster    │          │ Minecraft Cloud Bridge  │\n│   (Persistente Daten)   │          │ (RCON \u002F PaperMC \u002F Proxy)│\n└─────────────────────────┘          └─────────────────────────┘\n",[97,6088,6086],{"__ignoreMap":7},[29,6090],{},[32,6092,6094],{"id":6093},"_3-asynchrone-event-verteilung-mit-redis-pubsub","3. Asynchrone Event-Verteilung mit Redis Pub\u002FSub",[22,6096,6097],{},"Anstatt dass der Discord-Bot direkt den Minecraft-Server blockiert, kommunizieren die Services über leichtgewichtige Event-Channels:",[635,6099,6101],{"className":1071,"code":6100,"language":1073,"meta":7,"style":7},"\u002F\u002F bot-event-publisher.ts (Im Discord-Bot)\nimport Redis from 'ioredis';\n\nconst redis = new Redis();\n\nexport async function publishPlayerVerification(discordId: string, minecraftName: string) {\n  const eventPayload = {\n    type: 'PLAYER_VERIFIED',\n    discordId,\n    minecraftName,\n    timestamp: Date.now(),\n  };\n\n  \u002F\u002F Veröffentlichung im Redis Event-Bus in \u003C 1 ms\n  await redis.publish('events:player:verified', JSON.stringify(eventPayload));\n  console.log(`[Event Bus] Spieler-Verifizierung für ${minecraftName} publiziert.`);\n}\n",[97,6102,6103,6108,6126,6130,6148,6152,6185,6196,6212,6219,6226,6243,6247,6251,6256,6297,6328],{"__ignoreMap":7},[114,6104,6105],{"class":644,"line":552},[114,6106,6107],{"class":1142},"\u002F\u002F bot-event-publisher.ts (Im Discord-Bot)\n",[114,6109,6110,6112,6115,6117,6119,6122,6124],{"class":644,"line":537},[114,6111,1081],{"class":1080},[114,6113,6114],{"class":745}," Redis ",[114,6116,1087],{"class":1080},[114,6118,1090],{"class":735},[114,6120,6121],{"class":651},"ioredis",[114,6123,1095],{"class":735},[114,6125,1098],{"class":735},[114,6127,6128],{"class":644,"line":763},[114,6129,856],{"emptyLinePlaceholder":551},[114,6131,6132,6134,6137,6139,6141,6144,6146],{"class":644,"line":802},[114,6133,1108],{"class":1107},[114,6135,6136],{"class":745}," redis ",[114,6138,1114],{"class":735},[114,6140,1339],{"class":735},[114,6142,6143],{"class":1235}," Redis",[114,6145,1532],{"class":745},[114,6147,1098],{"class":735},[114,6149,6150],{"class":644,"line":808},[114,6151,856],{"emptyLinePlaceholder":551},[114,6153,6154,6156,6158,6160,6163,6165,6168,6170,6172,6174,6177,6179,6181,6183],{"class":644,"line":814},[114,6155,1152],{"class":1080},[114,6157,4354],{"class":1107},[114,6159,1232],{"class":1107},[114,6161,6162],{"class":1235}," publishPlayerVerification",[114,6164,1239],{"class":735},[114,6166,6167],{"class":1242},"discordId",[114,6169,1170],{"class":735},[114,6171,1173],{"class":647},[114,6173,1250],{"class":735},[114,6175,6176],{"class":1242}," minecraftName",[114,6178,1170],{"class":735},[114,6180,1173],{"class":647},[114,6182,1300],{"class":735},[114,6184,1161],{"class":735},[114,6186,6187,6189,6192,6194],{"class":644,"line":820},[114,6188,1270],{"class":1107},[114,6190,6191],{"class":745}," eventPayload",[114,6193,1276],{"class":735},[114,6195,1161],{"class":735},[114,6197,6198,6201,6203,6205,6208,6210],{"class":644,"line":826},[114,6199,6200],{"class":1166},"    type",[114,6202,1170],{"class":735},[114,6204,1090],{"class":735},[114,6206,6207],{"class":651},"PLAYER_VERIFIED",[114,6209,1095],{"class":735},[114,6211,1571],{"class":735},[114,6213,6214,6217],{"class":644,"line":832},[114,6215,6216],{"class":745},"    discordId",[114,6218,1571],{"class":735},[114,6220,6221,6224],{"class":644,"line":891},[114,6222,6223],{"class":745},"    minecraftName",[114,6225,1571],{"class":735},[114,6227,6228,6231,6233,6235,6237,6239,6241],{"class":644,"line":1204},[114,6229,6230],{"class":1166},"    timestamp",[114,6232,1170],{"class":735},[114,6234,3567],{"class":745},[114,6236,50],{"class":735},[114,6238,2796],{"class":1235},[114,6240,1532],{"class":1166},[114,6242,1571],{"class":735},[114,6244,6245],{"class":644,"line":1209},[114,6246,1611],{"class":735},[114,6248,6249],{"class":644,"line":1215},[114,6250,856],{"emptyLinePlaceholder":551},[114,6252,6253],{"class":644,"line":1221},[114,6254,6255],{"class":1142},"  \u002F\u002F Veröffentlichung im Redis Event-Bus in \u003C 1 ms\n",[114,6257,6258,6261,6264,6266,6269,6271,6273,6276,6278,6280,6283,6285,6288,6290,6293,6295],{"class":644,"line":1227},[114,6259,6260],{"class":1080},"  await",[114,6262,6263],{"class":745}," redis",[114,6265,50],{"class":735},[114,6267,6268],{"class":1235},"publish",[114,6270,1239],{"class":1166},[114,6272,1095],{"class":735},[114,6274,6275],{"class":651},"events:player:verified",[114,6277,1095],{"class":735},[114,6279,1250],{"class":735},[114,6281,6282],{"class":745}," JSON",[114,6284,50],{"class":735},[114,6286,6287],{"class":1235},"stringify",[114,6289,1239],{"class":1166},[114,6291,6292],{"class":745},"eventPayload",[114,6294,5036],{"class":1166},[114,6296,1098],{"class":735},[114,6298,6299,6301,6303,6305,6307,6309,6312,6314,6317,6319,6322,6324,6326],{"class":644,"line":1267},[114,6300,2641],{"class":745},[114,6302,50],{"class":735},[114,6304,2646],{"class":1235},[114,6306,1239],{"class":1166},[114,6308,2651],{"class":735},[114,6310,6311],{"class":651},"[Event Bus] Spieler-Verifizierung für ",[114,6313,2657],{"class":735},[114,6315,6316],{"class":745},"minecraftName",[114,6318,2693],{"class":735},[114,6320,6321],{"class":651}," publiziert.",[114,6323,2651],{"class":735},[114,6325,1300],{"class":1166},[114,6327,1098],{"class":735},[114,6329,6330],{"class":644,"line":1305},[114,6331,879],{"class":735},[22,6333,6334],{},"Auf der Empfänger-Seite:",[635,6336,6338],{"className":1071,"code":6337,"language":1073,"meta":7,"style":7},"\u002F\u002F minecraft-event-subscriber.ts (In der Minecraft Cloud Bridge)\nimport Redis from 'ioredis';\n\nconst subscriber = new Redis();\n\nsubscriber.subscribe('events:player:verified', () => {\n  console.log('[Subscriber] Höre auf Spieler-Verifizierungen...');\n});\n\nsubscriber.on('message', async (channel, message) => {\n  if (channel === 'events:player:verified') {\n    const data = JSON.parse(message);\n    \u002F\u002F Ausführung des Whitelist-Befehls auf dem Server via RCON\n    await executeSafeRconCommand(`whitelist add ${data.minecraftName}`);\n  }\n});\n",[97,6339,6340,6345,6361,6365,6382,6386,6412,6433,6441,6445,6481,6501,6526,6531,6561,6565],{"__ignoreMap":7},[114,6341,6342],{"class":644,"line":552},[114,6343,6344],{"class":1142},"\u002F\u002F minecraft-event-subscriber.ts (In der Minecraft Cloud Bridge)\n",[114,6346,6347,6349,6351,6353,6355,6357,6359],{"class":644,"line":537},[114,6348,1081],{"class":1080},[114,6350,6114],{"class":745},[114,6352,1087],{"class":1080},[114,6354,1090],{"class":735},[114,6356,6121],{"class":651},[114,6358,1095],{"class":735},[114,6360,1098],{"class":735},[114,6362,6363],{"class":644,"line":763},[114,6364,856],{"emptyLinePlaceholder":551},[114,6366,6367,6369,6372,6374,6376,6378,6380],{"class":644,"line":802},[114,6368,1108],{"class":1107},[114,6370,6371],{"class":745}," subscriber ",[114,6373,1114],{"class":735},[114,6375,1339],{"class":735},[114,6377,6143],{"class":1235},[114,6379,1532],{"class":745},[114,6381,1098],{"class":735},[114,6383,6384],{"class":644,"line":808},[114,6385,856],{"emptyLinePlaceholder":551},[114,6387,6388,6391,6393,6396,6398,6400,6402,6404,6406,6408,6410],{"class":644,"line":814},[114,6389,6390],{"class":745},"subscriber",[114,6392,50],{"class":735},[114,6394,6395],{"class":1235},"subscribe",[114,6397,1239],{"class":745},[114,6399,1095],{"class":735},[114,6401,6275],{"class":651},[114,6403,1095],{"class":735},[114,6405,1250],{"class":735},[114,6407,2906],{"class":735},[114,6409,2478],{"class":1107},[114,6411,1161],{"class":735},[114,6413,6414,6416,6418,6420,6422,6424,6427,6429,6431],{"class":644,"line":820},[114,6415,2641],{"class":745},[114,6417,50],{"class":735},[114,6419,2646],{"class":1235},[114,6421,1239],{"class":1166},[114,6423,1095],{"class":735},[114,6425,6426],{"class":651},"[Subscriber] Höre auf Spieler-Verifizierungen...",[114,6428,1095],{"class":735},[114,6430,1300],{"class":1166},[114,6432,1098],{"class":735},[114,6434,6435,6437,6439],{"class":644,"line":826},[114,6436,2693],{"class":735},[114,6438,1300],{"class":745},[114,6440,1098],{"class":735},[114,6442,6443],{"class":644,"line":832},[114,6444,856],{"emptyLinePlaceholder":551},[114,6446,6447,6449,6451,6453,6455,6457,6459,6461,6463,6465,6467,6470,6472,6475,6477,6479],{"class":644,"line":891},[114,6448,6390],{"class":745},[114,6450,50],{"class":735},[114,6452,2457],{"class":1235},[114,6454,1239],{"class":745},[114,6456,1095],{"class":735},[114,6458,2473],{"class":651},[114,6460,1095],{"class":735},[114,6462,1250],{"class":735},[114,6464,4354],{"class":1107},[114,6466,257],{"class":735},[114,6468,6469],{"class":1242},"channel",[114,6471,1250],{"class":735},[114,6473,6474],{"class":1242}," message",[114,6476,1300],{"class":735},[114,6478,2478],{"class":1107},[114,6480,1161],{"class":735},[114,6482,6483,6485,6487,6489,6491,6493,6495,6497,6499],{"class":644,"line":1204},[114,6484,1308],{"class":1080},[114,6486,257],{"class":1166},[114,6488,6469],{"class":745},[114,6490,4919],{"class":735},[114,6492,1090],{"class":735},[114,6494,6275],{"class":651},[114,6496,1095],{"class":735},[114,6498,1327],{"class":1166},[114,6500,1330],{"class":735},[114,6502,6503,6506,6509,6511,6513,6515,6518,6520,6522,6524],{"class":644,"line":1209},[114,6504,6505],{"class":1107},"    const",[114,6507,6508],{"class":745}," data",[114,6510,1276],{"class":735},[114,6512,6282],{"class":745},[114,6514,50],{"class":735},[114,6516,6517],{"class":1235},"parse",[114,6519,1239],{"class":1166},[114,6521,2473],{"class":745},[114,6523,1300],{"class":1166},[114,6525,1098],{"class":735},[114,6527,6528],{"class":644,"line":1215},[114,6529,6530],{"class":1142},"    \u002F\u002F Ausführung des Whitelist-Befehls auf dem Server via RCON\n",[114,6532,6533,6536,6539,6541,6543,6546,6548,6551,6553,6555,6557,6559],{"class":644,"line":1221},[114,6534,6535],{"class":1080},"    await",[114,6537,6538],{"class":1235}," executeSafeRconCommand",[114,6540,1239],{"class":1166},[114,6542,2651],{"class":735},[114,6544,6545],{"class":651},"whitelist add ",[114,6547,2657],{"class":735},[114,6549,6550],{"class":745},"data",[114,6552,50],{"class":735},[114,6554,6316],{"class":745},[114,6556,2933],{"class":735},[114,6558,1300],{"class":1166},[114,6560,1098],{"class":735},[114,6562,6563],{"class":644,"line":1227},[114,6564,817],{"class":735},[114,6566,6567,6569,6571],{"class":644,"line":1267},[114,6568,2693],{"class":735},[114,6570,1300],{"class":745},[114,6572,1098],{"class":735},[29,6574],{},[32,6576,6578],{"id":6577},"_4-architektonische-vorteile-für-gaming-communities","4. Architektonische Vorteile für Gaming-Communities",[70,6580,6581,6587,6593],{},[43,6582,6583,6586],{},[47,6584,6585],{},"Unabhängige Skalierbarkeit:"," Der Web-Server kann bei Traffic-Spitzen horizontal skaliert werden, ohne dass zusätzliche Bot-Verbindungen zu Discord aufgebaut werden müssen.",[43,6588,6589,6592],{},[47,6590,6591],{},"Fehlertoleranz:"," Wenn die Minecraft-Cloud-Bridge neu startet, puffert Redis anstehende Nachrichten. Weder der Bot noch das Dashboard stürzen ab.",[43,6594,6595,6598],{},[47,6596,6597],{},"Wartungsfreiheit:"," Jede Komponente kann unabhängig aktualisiert werden – maximale Uptime für deine Spieler und Community-Mitglieder.",[944,6600,6601],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":537,"depth":537,"links":6603},[6604,6605,6606,6607],{"id":6063,"depth":537,"text":6064},{"id":6078,"depth":537,"text":6079},{"id":6093,"depth":537,"text":6094},{"id":6577,"depth":537,"text":6578},{},"\u002Fdocs\u002Fde\u002Fmicroservices-gaming-networks",{"title":6611,"description":6051},{"Microservices vs Monolith für Gaming-Netzwerke":6612,"description":6613,"category":6614,"order":763,"author":2000,"readTime":5166,"lastUpdated":2002},"Skalierbare Discord & Minecraft Cloud","Architektur-Vergleich für wachsende Gaming-Communities. Entkopplung von Discord Bots, Web-Dashboards, Velocity Proxies und PostgreSQL.","architecture","docs\u002Fde\u002Fmicroservices-gaming-networks","kO6uuTt5P6GaQAySwt7c_9dpB6jq9gjYQT05pM986aE",{"id":6618,"title":6619,"author":12,"body":6620,"category":6873,"description":6874,"extension":549,"lastUpdated":12,"meta":6875,"navigation":551,"order":891,"path":6876,"readTime":12,"seo":6877,"stem":6878,"__hash__":6879},"docs\u002Fdocs\u002Fde\u002Fminecraft-dashboard.md","Minecraft Dashboard",{"type":14,"value":6621,"toc":6863},[6622,6625,6628,6632,6636,6639,6669,6673,6676,6696,6700,6703,6721,6732,6736,6739,6757,6759,6763,6766,6806,6810,6817,6824,6829],[17,6623,6619],{"id":6624},"minecraft-dashboard",[22,6626,6627],{},"Das KiroCloud Minecraft-Dashboard bietet eine zentrale Web-Oberfläche zur Verwaltung und Überwachung von Minecraft-Servern mit direkter Discord-Integration.",[32,6629,6631],{"id":6630},"kernfunktionen-des-dashboards","Kernfunktionen des Dashboards",[714,6633,6635],{"id":6634},"_1-echtzeit-konsole-telemetrie","1. Echtzeit-Konsole & Telemetrie",[22,6637,6638],{},"Sobald dein Server über das KiroCloud-Plugin verbunden ist, kannst du das Terminal direkt im Browser nutzen.",[40,6640,6641,6647,6663],{},[43,6642,6643,6646],{},[47,6644,6645],{},"Live-Logs:"," Die Server-Konsole wird über WebSockets in Echtzeit und latenzfrei in dein Dashboard gestreamt.",[43,6648,6649,6652,6653,381,6656,381,6659,6662],{},[47,6650,6651],{},"RCON Commands:"," Sende Befehle (z.B. ",[97,6654,6655],{},"\u002Fop",[97,6657,6658],{},"\u002Fgamemode",[97,6660,6661],{},"\u002Fkick",") direkt über das Web-Interface. Das System formatiert Minecraft-Farbscodes automatisch, sodass das Terminal wie das echte Spiel aussieht.",[43,6664,6665,6668],{},[47,6666,6667],{},"Performance-Graphen:"," Überwache TPS (Ticks per Second) und RAM-Auslastung in einem dynamischen Chart (Chart.js), um Server-Lags proaktiv zu erkennen.",[714,6670,6672],{"id":6671},"_2-spieler-management","2. Spieler-Management",[22,6674,6675],{},"Verwalte deine Community, ohne dich in das Spiel einloggen zu müssen.",[40,6677,6678,6684,6690],{},[43,6679,6680,6683],{},[47,6681,6682],{},"Spieler-Liste:"," Sieh sofort, wer online ist, inklusive deren Ping, Spielzeit und UUID.",[43,6685,6686,6689],{},[47,6687,6688],{},"Inventar & Statistiken:"," Mit einem Klick auf einen Spieler kannst du dessen Level, Gesundheit und Inventar-Inhalte betrachten.",[43,6691,6692,6695],{},[47,6693,6694],{},"Moderation:"," Banne, klicke oder mute Spieler mit vorgefertigten Quick-Actions.",[714,6697,6699],{"id":6698},"_3-dateimanager-file-explorer","3. Dateimanager (File Explorer)",[22,6701,6702],{},"Bearbeite Konfigurationsdateien direkt im Browser.",[40,6704,6705,6711,6718],{},[43,6706,6707,6708,261],{},"Navigiere durch die Ordnerstruktur deines Servers (z.B. ",[97,6709,6710],{},"\u002Fplugins\u002F",[43,6712,6713,6714,6717],{},"Öffne ",[97,6715,6716],{},"config.yml","-Dateien im integrierten Code-Editor (mit YAML\u002FJSON Syntax-Highlighting).",[43,6719,6720],{},"Lade neue Dateien hoch oder erstelle Zip-Archive für Backups.",[109,6722,6723],{},[22,6724,6725,6727,6728,6731],{},[114,6726,621],{},"\nDer Dateimanager hat direkten Schreibzugriff auf deinen Server. Lösche niemals Dateien aus dem ",[97,6729,6730],{},"\u002Fworld\u002F","-Verzeichnis, während der Server läuft, um Map-Korruption zu vermeiden!",[714,6733,6735],{"id":6734},"_4-modrinth-plugin-installer","4. Modrinth Plugin-Installer",[22,6737,6738],{},"Erweitere deinen Server mit wenigen Klicks.",[40,6740,6741,6744,6754],{},[43,6742,6743],{},"Suche nach Plugins direkt in der Modrinth-Datenbank.",[43,6745,6746,6747,6750,6751,6753],{},"Ein Klick auf \"Installieren\" lädt das ",[97,6748,6749],{},".jar","-File automatisch in deinen ",[97,6752,6710],{},"-Ordner herunter.",[43,6755,6756],{},"Beinhaltet automatische Überprüfung auf Inkompatibilitäten bezüglich deiner Server-Version.",[29,6758],{},[32,6760,6762],{"id":6761},"einrichtung-und-verbindung","Einrichtung und Verbindung",[22,6764,6765],{},"Um das Dashboard nutzen zu können, musst du das KiroCloud Connector-Plugin auf deinem Server installieren.",[70,6767,6768,6778,6790,6800],{},[43,6769,6770,6773,6774,6777],{},[47,6771,6772],{},"Plugin herunterladen:"," Lade die aktuelle ",[97,6775,6776],{},"KiroConnector.jar"," aus dem Dashboard herunter.",[43,6779,6780,6783,6784,6786,6787,6789],{},[47,6781,6782],{},"Installieren:"," Lege die ",[97,6785,6749],{},"-Datei in den ",[97,6788,6710],{}," Ordner deines Spigot\u002FPaper\u002FPurpur-Servers.",[43,6791,6792,6795,6796,6799],{},[47,6793,6794],{},"Konfigurieren:"," Starte den Server neu. Gehe in ",[97,6797,6798],{},"plugins\u002FKiroConnector\u002Fconfig.yml"," und trage deinen persönlichen KiroCloud API-Key ein, den du im Dashboard generiert hast.",[43,6801,6802,6805],{},[47,6803,6804],{},"Verbinden:"," Sobald der Server den Key verifiziert hat, wird der Status im Dashboard auf \"Online\" wechseln.",[32,6807,6809],{"id":6808},"discord-verknüpfung-account-sync","Discord-Verknüpfung (Account Sync)",[22,6811,6812,6813,6816],{},"Eine der beliebtesten Funktionen ist die ",[47,6814,6815],{},"Rollen-Synchronisierung"," zwischen Discord und Minecraft.",[22,6818,6819,6820,6823],{},"Nutzer können auf deiner KiroCloud-Instanz ihren Discord-Account mit ihrem Minecraft-Account verknüpfen (via ",[97,6821,6822],{},"\u002Fverify"," In-Game oder über das Webportal).",[22,6825,6826],{},[47,6827,6828],{},"Vorteile der Verknüpfung:",[40,6830,6831,6845,6851,6857],{},[43,6832,6833,6836,6837,6840,6841,6844],{},[47,6834,6835],{},"Rollen Sync:"," Ein User mit der Discord-Rolle ",[97,6838,6839],{},"@VIP"," erhält automatisch In-Game die Gruppe ",[97,6842,6843],{},"vip"," (kompatibel mit LuckPerms).",[43,6846,6847,6850],{},[47,6848,6849],{},"Namens-Synchronisation:"," Der Discord-Nickname kann automatisch auf den Minecraft-Benutzernamen gesetzt werden.",[43,6852,6853,6856],{},[47,6854,6855],{},"Booster-Belohnungen:"," Server-Booster auf Discord erhalten automatisch In-Game-Items oder temporäre Ränge.",[43,6858,6859,6862],{},[47,6860,6861],{},"Whitelisting:"," Nur Nutzer, die in Discord Mitglied deines Servers sind, können dem Minecraft-Server beitreten.",{"title":7,"searchDepth":537,"depth":537,"links":6864},[6865,6871,6872],{"id":6630,"depth":537,"text":6631,"children":6866},[6867,6868,6869,6870],{"id":6634,"depth":763,"text":6635},{"id":6671,"depth":763,"text":6672},{"id":6698,"depth":763,"text":6699},{"id":6734,"depth":763,"text":6735},{"id":6761,"depth":537,"text":6762},{"id":6808,"depth":537,"text":6809},"features","Verwalte, überwache und steuere deinen Minecraft-Server direkt über KiroCloud.",{},"\u002Fdocs\u002Fde\u002Fminecraft-dashboard",{"title":6619,"description":6874},"docs\u002Fde\u002Fminecraft-dashboard","UOecQ4AiepybP0LYFttN3mCMKc-EMk87LJryNL8kmJM",{"id":6881,"title":969,"author":12,"body":6882,"category":12,"description":6890,"extension":549,"lastUpdated":12,"meta":7323,"navigation":551,"order":962,"path":7324,"readTime":12,"seo":7325,"stem":7329,"__hash__":7330},"docs\u002Fdocs\u002Fde\u002Fminecraft-engine-benchmarks.md",{"type":14,"value":6883,"toc":7313},[6884,6888,6891,6904,6906,6910,6940,6946,6948,6952,6956,6959,6979,6983,6986,7003,7007,7022,7043,7045,7049,7056,7204,7206,7210,7310],[17,6885,6887],{"id":6886},"minecraft-server-engine-benchmark-papermc-vs-purpur-vs-fabric-performance-vergleich","Minecraft Server Engine Benchmark: PaperMC vs Purpur vs Fabric Performance-Vergleich",[22,6889,6890],{},"Die Wahl der richtigen Server-Software entscheidet maßgeblich über die Performance, Lag-Freiheit und maximale Spieleranzahl eines Minecraft-Servers. Während der offizielle Vanilla-Server bereits bei 10 gleichzeitig aktiven Spielern und automatisierter Redstone-Technik unter 15 TPS (Ticks Per Second) einbrechen kann, existieren hochoptimierte Server-Forks und Mod-Loader.",[22,6892,6893,6894,381,6897,186,6900,6903],{},"In diesem Benchmark vergleichen wir die drei beliebtesten Plattformen – ",[47,6895,6896],{},"PaperMC",[47,6898,6899],{},"Purpur",[47,6901,6902],{},"Fabric"," – unter realen Lastbedingungen auf dedizierten Multi-Core Host-Systemen mit NVMe-Speicher in der deutschen Server-Infrastruktur von KiroCloud.",[29,6905],{},[32,6907,6909],{"id":6908},"_1-die-testumgebung-benchmark-methodik","1. Die Testumgebung & Benchmark-Methodik",[40,6911,6912,6918,6924],{},[43,6913,6914,6917],{},[47,6915,6916],{},"Host-Hardware:"," High-Performance Multi-Core CPU, Enterprise PCIe NVMe, High-Speed RAM.",[43,6919,6920,6923],{},[47,6921,6922],{},"Minecraft-Version:"," 1.21.1 (Java 21).",[43,6925,6926,6929],{},[47,6927,6928],{},"Test-Szenario:",[40,6930,6931,6934,6937],{},[43,6932,6933],{},"50 simulierte Spieler in 5 verschiedenen Chunks mit Elytren-Flug (aggressive Chunk-Generierung).",[43,6935,6936],{},"10 automatisierte Villager-Trading-Farmen und 1.000 aktive Mobs.",[43,6938,6939],{},"Laufzeit: 60 Minuten kontinuierlicher Lasttest.",[635,6941,6944],{"className":6942,"code":6943,"language":1053},[1051],"┌────────────────────────────────────────────────────────┐\n│             Durchschnittliche Tick-Latenz (MSPT)       │\n│             (Niedriger ist besser | Ziel: \u003C 50 ms)     │\n├─────────────────┬──────────────────────────────────────┤\n│ Vanilla         │ ████████████████████████████ 78.4 ms │ (Einbruch auf 12.8 TPS)\n│ Fabric + Lithium│ ████████████ 32.1 ms                 │ (Stabile 20.0 TPS)\n│ PaperMC         │ █████████ 24.6 ms                    │ (Stabile 20.0 TPS)\n│ Purpur          │ ███████ 19.8 ms                      │ (Stabile 20.0 TPS)\n└─────────────────┴──────────────────────────────────────┘\n",[97,6945,6943],{"__ignoreMap":7},[29,6947],{},[32,6949,6951],{"id":6950},"_2-detaillierter-vergleich-der-plattformen","2. Detaillierter Vergleich der Plattformen",[714,6953,6955],{"id":6954},"a-papermc-der-industriestandard-für-stabilität","A. PaperMC: Der Industriestandard für Stabilität",[22,6957,6958],{},"PaperMC ist der meistgenutzte Fork für Spigot\u002FBukkit-Server.",[40,6960,6961,6967,6973],{},[43,6962,6963,6966],{},[47,6964,6965],{},"Vorteile:"," Asynchrone Chunk-Ladevorgänge, optimierte Entity-Kollisionsberechnung, umfangreicher Exploit-Schutz und maximale Plugin-Kompatibilität.",[43,6968,6969,6972],{},[47,6970,6971],{},"Nachteile:"," Verändert minimale Vanilla-Redstone-Ticks (kann komplexe technische Redstone-Schaltungen geringfügig beeinflussen).",[43,6974,6975,6978],{},[47,6976,6977],{},"Ideal für:"," Große Community-Server, Citybuild, Minigames und Netzwerke mit klassischen Bukkit\u002FSpigot-Plugins.",[714,6980,6982],{"id":6981},"b-purpur-maximale-anpassung-performance-tweaks","B. Purpur: Maximale Anpassung & Performance-Tweaks",[22,6984,6985],{},"Purpur basiert direkt auf Paper und fügt zusätzliche Performance- und Gameplay-Optionen hinzu.",[40,6987,6988,6993,6998],{},[43,6989,6990,6992],{},[47,6991,6965],{}," Bietet zusätzliche Einstellungen zum Deaktivieren von ungenutzter Entity-KI (z. B. inaktive Fische oder Schafe), alternative Entity-Deduplizierung und fein justierbare Tick-Raten für Hoppers.",[43,6994,6995,6997],{},[47,6996,6971],{}," Noch tiefere Eingriffe in Vanilla-Verhalten, die bei falscher Konfiguration auffallen können.",[43,6999,7000,7002],{},[47,7001,6977],{}," Große Survival- und SkyBlock-Server mit hohen Mob-Zahlen.",[714,7004,7006],{"id":7005},"c-fabric-mit-lithium-ferritecore-das-vanilla-original","C. Fabric (mit Lithium & FerriteCore): Das Vanilla-Original",[22,7008,7009,7010,7013,7014,7017,7018,7021],{},"Fabric ist ein modularer Mod-Loader, der durch Optimierungs-Mods wie ",[47,7011,7012],{},"Lithium"," (CPU-Optimierung), ",[47,7015,7016],{},"FerriteCore"," (RAM-Reduktion) und ",[47,7019,7020],{},"Krypton"," (Netzwerk-Stack) extrem schnell wird.",[40,7023,7024,7033,7038],{},[43,7025,7026,7028,7029,7032],{},[47,7027,6965],{}," Verändert ",[47,7030,7031],{},"keinerlei"," Vanilla-Spielmechaniken. 100 % kompatibel mit technischen Redstone-Maschinen und Farmen.",[43,7034,7035,7037],{},[47,7036,6971],{}," Keine Unterstützung für Bukkit-Plugins (WorldEdit, LuckPerms müssen als Fabric-Mods installiert werden).",[43,7039,7040,7042],{},[47,7041,6977],{}," Technische Vanilla-Server, Scicraft-ähnliche Projekte und Modded-Communities.",[29,7044],{},[32,7046,7048],{"id":7047},"_3-optimale-jvm-flags-für-kirocloud-server","3. Optimale JVM-Flags für KiroCloud Server",[22,7050,7051,7052,7055],{},"Unabhängig von der Engine ist die Konfiguration der Java Virtual Machine entscheidend. Wir empfehlen die ",[47,7053,7054],{},"Aikar Flags"," in Kombination mit dem ZGC- oder G1GC-Garbage-Collector:",[635,7057,7059],{"className":637,"code":7058,"language":639,"meta":7,"style":7},"java -Xms4G -Xmx4G \\\n  -XX:+UseG1GC \\\n  -XX:+ParallelRefProcEnabled \\\n  -XX:MaxGCPauseMillis=200 \\\n  -XX:+UnlockExperimentalVMOptions \\\n  -XX:+DisableExplicitGC \\\n  -XX:+AlwaysPreTouch \\\n  -XX:G1NewSizePercent=30 \\\n  -XX:G1MaxNewSizePercent=40 \\\n  -XX:G1ReservePercent=20 \\\n  -XX:G1HeapWastePercent=5 \\\n  -XX:G1MixedGCCountTarget=4 \\\n  -XX:InitiatingHeapOccupancyPercent=15 \\\n  -XX:G1MixedGCLiveThresholdPercent=90 \\\n  -XX:G1RSetUpdatingPauseTimePercent=5 \\\n  -XX:SurvivorRatio=32 \\\n  -XX:+PerfDisableSharedMem \\\n  -XX:MaxTenuringThreshold=1 \\\n  -jar server.jar nogui\n",[97,7060,7061,7074,7081,7088,7095,7102,7109,7116,7123,7130,7137,7144,7151,7158,7165,7172,7179,7186,7193],{"__ignoreMap":7},[114,7062,7063,7066,7069,7072],{"class":644,"line":552},[114,7064,7065],{"class":647},"java",[114,7067,7068],{"class":651}," -Xms4G",[114,7070,7071],{"class":651}," -Xmx4G",[114,7073,746],{"class":745},[114,7075,7076,7079],{"class":644,"line":537},[114,7077,7078],{"class":651},"  -XX:+UseG1GC",[114,7080,746],{"class":745},[114,7082,7083,7086],{"class":644,"line":763},[114,7084,7085],{"class":651},"  -XX:+ParallelRefProcEnabled",[114,7087,746],{"class":745},[114,7089,7090,7093],{"class":644,"line":802},[114,7091,7092],{"class":651},"  -XX:MaxGCPauseMillis=200",[114,7094,746],{"class":745},[114,7096,7097,7100],{"class":644,"line":808},[114,7098,7099],{"class":651},"  -XX:+UnlockExperimentalVMOptions",[114,7101,746],{"class":745},[114,7103,7104,7107],{"class":644,"line":814},[114,7105,7106],{"class":651},"  -XX:+DisableExplicitGC",[114,7108,746],{"class":745},[114,7110,7111,7114],{"class":644,"line":820},[114,7112,7113],{"class":651},"  -XX:+AlwaysPreTouch",[114,7115,746],{"class":745},[114,7117,7118,7121],{"class":644,"line":826},[114,7119,7120],{"class":651},"  -XX:G1NewSizePercent=30",[114,7122,746],{"class":745},[114,7124,7125,7128],{"class":644,"line":832},[114,7126,7127],{"class":651},"  -XX:G1MaxNewSizePercent=40",[114,7129,746],{"class":745},[114,7131,7132,7135],{"class":644,"line":891},[114,7133,7134],{"class":651},"  -XX:G1ReservePercent=20",[114,7136,746],{"class":745},[114,7138,7139,7142],{"class":644,"line":1204},[114,7140,7141],{"class":651},"  -XX:G1HeapWastePercent=5",[114,7143,746],{"class":745},[114,7145,7146,7149],{"class":644,"line":1209},[114,7147,7148],{"class":651},"  -XX:G1MixedGCCountTarget=4",[114,7150,746],{"class":745},[114,7152,7153,7156],{"class":644,"line":1215},[114,7154,7155],{"class":651},"  -XX:InitiatingHeapOccupancyPercent=15",[114,7157,746],{"class":745},[114,7159,7160,7163],{"class":644,"line":1221},[114,7161,7162],{"class":651},"  -XX:G1MixedGCLiveThresholdPercent=90",[114,7164,746],{"class":745},[114,7166,7167,7170],{"class":644,"line":1227},[114,7168,7169],{"class":651},"  -XX:G1RSetUpdatingPauseTimePercent=5",[114,7171,746],{"class":745},[114,7173,7174,7177],{"class":644,"line":1267},[114,7175,7176],{"class":651},"  -XX:SurvivorRatio=32",[114,7178,746],{"class":745},[114,7180,7181,7184],{"class":644,"line":1305},[114,7182,7183],{"class":651},"  -XX:+PerfDisableSharedMem",[114,7185,746],{"class":745},[114,7187,7188,7191],{"class":644,"line":1333},[114,7189,7190],{"class":651},"  -XX:MaxTenuringThreshold=1",[114,7192,746],{"class":745},[114,7194,7195,7198,7201],{"class":644,"line":1358},[114,7196,7197],{"class":651},"  -jar",[114,7199,7200],{"class":651}," server.jar",[114,7202,7203],{"class":651}," nogui\n",[29,7205],{},[32,7207,7209],{"id":7208},"_4-fazit-empfehlung","4. Fazit & Empfehlung",[447,7211,7212,7226],{},[450,7213,7214],{},[453,7215,7216,7219,7221,7223],{},[456,7217,7218],{},"Kriterium",[456,7220,6896],{},[456,7222,6899],{},[456,7224,7225],{},"Fabric (Lithium)",[467,7227,7228,7243,7261,7278,7294],{},[453,7229,7230,7235,7238,7240],{},[472,7231,7232],{},[47,7233,7234],{},"Plugin-Ökosystem",[472,7236,7237],{},"Exzellent (Bukkit\u002FPaper)",[472,7239,7237],{},[472,7241,7242],{},"Nur Fabric-Mods",[453,7244,7245,7250,7253,7256],{},[472,7246,7247],{},[47,7248,7249],{},"Vanilla-Exaktheit",[472,7251,7252],{},"92 %",[472,7254,7255],{},"88 %",[472,7257,7258],{},[47,7259,7260],{},"100 %",[453,7262,7263,7268,7271,7276],{},[472,7264,7265],{},[47,7266,7267],{},"Entity-Performance",[472,7269,7270],{},"Sehr gut",[472,7272,7273],{},[47,7274,7275],{},"Hervorragend",[472,7277,7270],{},[453,7279,7280,7285,7288,7290],{},[472,7281,7282],{},[47,7283,7284],{},"RAM-Effizienz",[472,7286,7287],{},"Gut",[472,7289,7287],{},[472,7291,7292],{},[47,7293,7270],{},[453,7295,7296,7301,7304,7307],{},[472,7297,7298],{},[47,7299,7300],{},"KiroCloud Empfehlung",[472,7302,7303],{},"Standard für Public Server",[472,7305,7306],{},"High-Mob Server",[472,7308,7309],{},"Technische Communities",[944,7311,7312],{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":537,"depth":537,"links":7314},[7315,7316,7321,7322],{"id":6908,"depth":537,"text":6909},{"id":6950,"depth":537,"text":6951,"children":7317},[7318,7319,7320],{"id":6954,"depth":763,"text":6955},{"id":6981,"depth":763,"text":6982},{"id":7005,"depth":763,"text":7006},{"id":7047,"depth":537,"text":7048},{"id":7208,"depth":537,"text":7209},{},"\u002Fdocs\u002Fde\u002Fminecraft-engine-benchmarks",{"title":7326,"description":6890},{"Minecraft Server Engine Benchmark":7327,"description":7328,"category":6034,"order":552,"author":2000,"readTime":2001,"lastUpdated":2002},"PaperMC vs Purpur vs Fabric Performance-Vergleich","Benchmarks für Minecraft-Serversoftware. Single-Core Tick-Loop, Chunk-Generierung, RAM-Allokation und Mod- vs. Plugin-Architektur im Vergleich.","docs\u002Fde\u002Fminecraft-engine-benchmarks","xX-_pJk-VAy0jCWLyCGHMPnnViek9JFcA2vIQpVX9Hk",{"id":7332,"title":7333,"author":12,"body":7334,"category":7959,"description":7960,"extension":549,"lastUpdated":12,"meta":7961,"navigation":551,"order":552,"path":7962,"readTime":12,"seo":7963,"stem":7964,"__hash__":7965},"docs\u002Fdocs\u002Fde\u002Fminecraft-link.md","Minecraft-Server verknüpfen",{"type":14,"value":7335,"toc":7945},[7336,7340,7343,7345,7349,7352,7360,7366,7393,7408,7412,7485,7487,7491,7494,7518,7559,7561,7565,7568,7572,7764,7771,7773,7777,7784,7819,7821,7825,7828,7846,7848,7852,7942],[17,7337,7339],{"id":7338},"minecraft-server-mit-kirocloud-verknüpfen","Minecraft-Server mit KiroCloud verknüpfen",[22,7341,7342],{},"Die Verbindung zwischen deinem Minecraft-Server, KiroCloud und deinem Discord-Server synchronisiert Spielerränge automatisch mit Discord-Rollen, verwaltet Whitelists, führt In-Game-Verifikationen durch und sendet RCON-Befehle über das Web-Dashboard.",[29,7344],{},[32,7346,7348],{"id":7347},"_1-rcon-einrichtung-auf-dem-minecraft-server","1. RCON-Einrichtung auf dem Minecraft-Server",[22,7350,7351],{},"RCON (Remote Console) ist das Standard-Protokoll, mit dem KiroCloud Befehle an deinen Minecraft-Server übermittelt (z. B. für Verifizierungscodes, Rang-Updates oder Whitelisting).",[714,7353,7355,7356,7359],{"id":7354},"schritt-1-serverproperties-anpassen","Schritt 1: ",[97,7357,7358],{},"server.properties"," anpassen",[22,7361,7362,7363,7365],{},"Öffne die Datei ",[97,7364,7358],{}," im Hauptverzeichnis deines Minecraft-Servers und setze folgende Werte:",[635,7367,7371],{"className":7368,"code":7369,"language":7370,"meta":7,"style":7},"language-properties shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","enable-rcon=true\nrcon.port=25575\nrcon.password=DEIN_SICHERES_RCON_PASSWORT\nbroadcast-rcon-to-ops=false\n","properties",[97,7372,7373,7378,7383,7388],{"__ignoreMap":7},[114,7374,7375],{"class":644,"line":552},[114,7376,7377],{},"enable-rcon=true\n",[114,7379,7380],{"class":644,"line":537},[114,7381,7382],{},"rcon.port=25575\n",[114,7384,7385],{"class":644,"line":763},[114,7386,7387],{},"rcon.password=DEIN_SICHERES_RCON_PASSWORT\n",[114,7389,7390],{"class":644,"line":802},[114,7391,7392],{},"broadcast-rcon-to-ops=false\n",[109,7394,7395],{},[22,7396,7397,7399,7400,7403,7404,7407],{},[114,7398,621],{},"\nVerwende ein langes, zufällig generiertes Passwort für ",[97,7401,7402],{},"rcon.password",". Der RCON-Port (",[97,7405,7406],{},"25575",") muss in deiner Firewall bzw. deinem Router (Port-Forwarding) für TCP-Verbindungen freigegeben sein.",[714,7409,7411],{"id":7410},"schritt-2-server-in-kirocloud-eintragen","Schritt 2: Server in KiroCloud eintragen",[70,7413,7414,7424,7429,7476],{},[43,7415,7416,7417,7420,7421,261],{},"Navigiere im KiroCloud Dashboard zu ",[47,7418,7419],{},"Minecraft > Serververwaltung"," (oder ",[97,7422,7423],{},"\u002Fadmin\u002Fminecraft",[43,7425,103,7426,50],{},[47,7427,7428],{},"\"Server hinzufügen\"",[43,7430,7431,7432],{},"Gib folgende Verbindungsdaten ein:\n",[40,7433,7434,7443,7449,7460,7466],{},[43,7435,7436,7439,7440],{},[47,7437,7438],{},"Server-Name:"," z. B. ",[97,7441,7442],{},"CityBuild-01",[43,7444,7445,7448],{},[47,7446,7447],{},"Host \u002F IP:"," Die öffentliche IP-Adresse oder Domain deines Minecraft-Servers.",[43,7450,7451,7454,7455,7457,7458,261],{},[47,7452,7453],{},"RCON-Port:"," Der in ",[97,7456,7358],{}," definierte Port (Standard: ",[97,7459,7406],{},[43,7461,7462,7465],{},[47,7463,7464],{},"RCON-Passwort:"," Das vergebene Passwort.",[43,7467,7468,7471,7472,7475],{},[47,7469,7470],{},"Server-Typ:"," Wähle ",[97,7473,7474],{},"Hauptserver (Main)"," für den primären Verifikations-Server.",[43,7477,103,7478,7481,7482,50],{},[47,7479,7480],{},"\"Verbindung testen\""," und anschließend auf ",[47,7483,7484],{},"\"Speichern\"",[29,7486],{},[32,7488,7490],{"id":7489},"_2-kiroconnector-plugin-api-token","2. KiroConnector Plugin & API-Token",[22,7492,7493],{},"Für erweiterte Funktionen wie Live-Chat-Bridge, TPS-Telemetrie und Spieler-Inventar-Abfragen installierst du unser leichtgewichtiges Connector-Plugin.",[70,7495,7496,7504,7510,7513],{},[43,7497,7498,7499,7503],{},"Lade die aktuelle Version von ",[47,7500,7501],{},[97,7502,6776],{}," im KiroCloud Dashboard herunter.",[43,7505,7506,7507,7509],{},"Lege die Datei in den ",[97,7508,6710],{},"-Ordner deines Spigot-, Paper- oder Purpur-Servers.",[43,7511,7512],{},"Starte den Server neu, damit die Konfigurationsdatei generiert wird.",[43,7514,6713,7515,7517],{},[97,7516,6798],{}," und trage deinen Server-Token ein:",[635,7519,7523],{"className":7520,"code":7521,"language":7522,"meta":7,"style":7},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","server-token: \"kiro_srv_dein_geheimer_token\"\nsync-interval-seconds: 15\ndebug: false\n","yaml",[97,7524,7525,7539,7549],{"__ignoreMap":7},[114,7526,7527,7530,7532,7534,7537],{"class":644,"line":552},[114,7528,7529],{"class":1166},"server-token",[114,7531,1170],{"class":735},[114,7533,736],{"class":735},[114,7535,7536],{"class":651},"kiro_srv_dein_geheimer_token",[114,7538,773],{"class":735},[114,7540,7541,7544,7546],{"class":644,"line":537},[114,7542,7543],{"class":1166},"sync-interval-seconds",[114,7545,1170],{"class":735},[114,7547,7548],{"class":1135}," 15\n",[114,7550,7551,7554,7556],{"class":644,"line":763},[114,7552,7553],{"class":1166},"debug",[114,7555,1170],{"class":735},[114,7557,7558],{"class":3897}," false\n",[29,7560],{},[32,7562,7564],{"id":7563},"_3-account-verifikation-discord-minecraft","3. Account-Verifikation (Discord \u003C-> Minecraft)",[22,7566,7567],{},"KiroCloud bietet einen sicheren und benutzerfreundlichen Verifikationsprozess, um Discord-Accounts mit Minecraft-Spielernamen zu verknüpfen.",[714,7569,7571],{"id":7570},"der-verifikationsablauf","Der Verifikationsablauf:",[70,7573,7574,7587,7597,7748,7758],{},[43,7575,7576,7579,7580,7583,7584,50],{},[47,7577,7578],{},"Ablauf starten:"," Ein Spieler klickt im Discord auf den Button ",[47,7581,7582],{},"\"Minecraft-Account verknüpfen\""," oder nutzt den Slash-Command ",[97,7585,7586],{},"\u002Fverify minecraft \u003Cusername>",[43,7588,7589,7592,7593,7596],{},[47,7590,7591],{},"Namen eingeben:"," Ein Modal öffnet sich, in dem der Spieler seinen Minecraft-Namen (z. B. ",[97,7594,7595],{},"Steve",") eingibt.",[43,7598,7599,7602,7603,7606,7607],{},[47,7600,7601],{},"Code via RCON senden:"," KiroCloud generiert einen zufälligen 6-stelligen Zahlencode (10 Minuten gültig) und sendet ihn per In-Game-Nachricht (",[97,7604,7605],{},"tellraw",") direkt an den Spieler:\n",[635,7608,7612],{"className":7609,"code":7610,"language":7611,"meta":7,"style":7},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[\"\",{\"text\":\"[KiroCloud] \",\"color\":\"gold\",\"bold\":true},{\"text\":\"Dein Verifizierungscode ist: \",\"color\":\"gray\"},{\"text\":\"482910\",\"color\":\"green\",\"bold\":true}]\n","json",[97,7613,7614],{"__ignoreMap":7},[114,7615,7616,7619,7622,7625,7627,7629,7631,7633,7635,7638,7640,7642,7644,7647,7649,7651,7653,7656,7658,7660,7662,7665,7667,7670,7672,7674,7676,7678,7680,7683,7685,7687,7689,7691,7693,7695,7697,7700,7702,7705,7707,7709,7711,7713,7715,7718,7720,7722,7724,7726,7728,7730,7732,7735,7737,7739,7741,7743,7745],{"class":644,"line":552},[114,7617,7618],{"class":735},"[",[114,7620,7621],{"class":735},"\"\"",[114,7623,7624],{"class":735},",{",[114,7626,742],{"class":735},[114,7628,1053],{"class":1107},[114,7630,742],{"class":735},[114,7632,1170],{"class":735},[114,7634,742],{"class":735},[114,7636,7637],{"class":651},"[KiroCloud] ",[114,7639,742],{"class":735},[114,7641,1250],{"class":735},[114,7643,742],{"class":735},[114,7645,7646],{"class":1107},"color",[114,7648,742],{"class":735},[114,7650,1170],{"class":735},[114,7652,742],{"class":735},[114,7654,7655],{"class":651},"gold",[114,7657,742],{"class":735},[114,7659,1250],{"class":735},[114,7661,742],{"class":735},[114,7663,7664],{"class":1107},"bold",[114,7666,742],{"class":735},[114,7668,7669],{"class":735},":true},{",[114,7671,742],{"class":735},[114,7673,1053],{"class":1107},[114,7675,742],{"class":735},[114,7677,1170],{"class":735},[114,7679,742],{"class":735},[114,7681,7682],{"class":651},"Dein Verifizierungscode ist: ",[114,7684,742],{"class":735},[114,7686,1250],{"class":735},[114,7688,742],{"class":735},[114,7690,7646],{"class":1107},[114,7692,742],{"class":735},[114,7694,1170],{"class":735},[114,7696,742],{"class":735},[114,7698,7699],{"class":651},"gray",[114,7701,742],{"class":735},[114,7703,7704],{"class":735},"},{",[114,7706,742],{"class":735},[114,7708,1053],{"class":1107},[114,7710,742],{"class":735},[114,7712,1170],{"class":735},[114,7714,742],{"class":735},[114,7716,7717],{"class":651},"482910",[114,7719,742],{"class":735},[114,7721,1250],{"class":735},[114,7723,742],{"class":735},[114,7725,7646],{"class":1107},[114,7727,742],{"class":735},[114,7729,1170],{"class":735},[114,7731,742],{"class":735},[114,7733,7734],{"class":651},"green",[114,7736,742],{"class":735},[114,7738,1250],{"class":735},[114,7740,742],{"class":735},[114,7742,7664],{"class":1107},[114,7744,742],{"class":735},[114,7746,7747],{"class":735},":true}]\n",[43,7749,7750,7753,7754,7757],{},[47,7751,7752],{},"Code eingeben:"," Der Spieler klickt im Discord auf ",[47,7755,7756],{},"\"Code eingeben\"",", trägt die 6 Ziffern ein und bestätigt.",[43,7759,7760,7763],{},[47,7761,7762],{},"Erfolgreiche Verknüpfung:"," Der Account wird in der Datenbank verknüpft, das Profilbild wird mit dem Minecraft-Skin aktualisiert und die konfigurierten Discord-Rollen werden vergeben.",[109,7765,7766],{},[22,7767,7768,7770],{},[114,7769,2184],{},"\nDer Spieler muss sich während der Verifikation auf dem Server befinden, um den In-Game-Code empfangen zu können.",[29,7772],{},[32,7774,7776],{"id":7775},"_4-rang-rollen-synchronisation","4. Rang- & Rollen-Synchronisation",[22,7778,7779,7780,7783],{},"Mit der Rang-Synchronisation spiegelst du Discord-Rollen und Minecraft-Rechtegruppen (z. B. via ",[47,7781,7782],{},"LuckPerms",") automatisch wider:",[40,7785,7786,7802,7808,7813],{},[43,7787,7788,7791,7792,3008,7794,7797,7798,7801],{},[47,7789,7790],{},"Discord zu Minecraft (In-Game Ränge):"," Wenn ein Nutzer auf Discord eine bestimmte Rolle erhält (z. B. ",[97,7793,6839],{},[97,7795,7796],{},"@Supporter","), führt KiroCloud via RCON automatisch den Befehl ",[97,7799,7800],{},"lp user \u003Cplayer> parent add vip"," aus.",[43,7803,7804,7807],{},[47,7805,7806],{},"Minecraft zu Discord:"," In-Game gekaufte oder vergebene Ränge können umgekehrt entsprechende Discord-Rollen zuweisen.",[43,7809,7810,7812],{},[47,7811,6855],{}," Discord-Server-Booster erhalten automatisch In-Game-Vorteile (z. B. Kosmetika, Geld oder temporäre VIP-Ränge).",[43,7814,7815,7818],{},[47,7816,7817],{},"Nickname-Synchronisation:"," Der Discord-Server-Nickname des Nutzers kann automatisch auf seinen Minecraft-Namen gesetzt werden.",[29,7820],{},[32,7822,7824],{"id":7823},"_5-whitelist-verwaltung-zugangskontrolle","5. Whitelist-Verwaltung & Zugangskontrolle",[22,7826,7827],{},"Schütze deinen Server vor Fremdzugriffen durch automatisiertes Whitelisting:",[40,7829,7830,7840],{},[43,7831,7832,7835,7836,7839],{},[47,7833,7834],{},"Discord-Only Modus:"," Nur Mitglieder deines Discord-Servers, die ihren Account erfolgreich verifiziert haben, werden automatisch per ",[97,7837,7838],{},"whitelist add \u003Cplayer>"," auf die Server-Whitelist gesetzt.",[43,7841,7842,7845],{},[47,7843,7844],{},"Auto-Revoke bei Server-Austritt:"," Verlässt ein Mitglied deinen Discord-Server oder wird gesperrt, entfernt KiroCloud den Spieler sofort von der Whitelist und führt bei Bedarf einen In-Game-Kick durch.",[29,7847],{},[32,7849,7851],{"id":7850},"_6-fehlerbehebung-troubleshooting","6. Fehlerbehebung & Troubleshooting",[447,7853,7854,7866],{},[450,7855,7856],{},[453,7857,7858,7861,7864],{},[456,7859,7860],{"align":458},"Fehlerbild",[456,7862,7863],{"align":458},"Mögliche Ursache",[456,7865,465],{"align":458},[467,7867,7868,7889,7908,7925],{},[453,7869,7870,7875,7878],{},[472,7871,7872],{"align":458},[47,7873,7874],{},"RCON Connection Refused \u002F Timeout",[472,7876,7877],{"align":458},"Port nicht freigegeben oder falsche IP",[472,7879,7880,7881,7884,7885,7888],{"align":458},"Überprüfe Port-Forwarding (",[97,7882,7883],{},"25575 TCP",") und stelle sicher, dass ",[97,7886,7887],{},"enable-rcon=true"," aktiv ist.",[453,7890,7891,7896,7899],{},[472,7892,7893],{"align":458},[47,7894,7895],{},"RCON Authentication Failed",[472,7897,7898],{"align":458},"Passwort falsch eingegeben",[472,7900,7901,7902,7904,7905,7907],{"align":458},"Vergleiche ",[97,7903,7402],{}," in ",[97,7906,7358],{}," exakt mit dem Eintrag in KiroCloud.",[453,7909,7910,7915,7918],{},[472,7911,7912],{"align":458},[47,7913,7914],{},"\"Spieler nicht online\"-Fehler",[472,7916,7917],{"align":458},"Spieler befindet sich nicht auf dem Server",[472,7919,7920,7921,7924],{"align":458},"Der Spieler muss auf dem Server eingeloggt sein, um den Code via ",[97,7922,7923],{},"\u002Ftellraw"," zu empfangen.",[453,7926,7927,7932,7935],{},[472,7928,7929],{"align":458},[47,7930,7931],{},"LuckPerms-Ränge werden nicht gesetzt",[472,7933,7934],{"align":458},"Fehlende Rechte oder falscher Gruppenname",[472,7936,7937,7938,7941],{"align":458},"Überprüfe den Gruppennamen in LuckPerms (",[97,7939,7940],{},"\u002Flp listgroups",") und stelle sicher, dass der Bot OP-\u002FRCON-Rechte hat.",[944,7943,7944],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":7,"searchDepth":537,"depth":537,"links":7946},[7947,7952,7953,7956,7957,7958],{"id":7347,"depth":537,"text":7348,"children":7948},[7949,7951],{"id":7354,"depth":763,"text":7950},"Schritt 1: server.properties anpassen",{"id":7410,"depth":763,"text":7411},{"id":7489,"depth":537,"text":7490},{"id":7563,"depth":537,"text":7564,"children":7954},[7955],{"id":7570,"depth":763,"text":7571},{"id":7775,"depth":537,"text":7776},{"id":7823,"depth":537,"text":7824},{"id":7850,"depth":537,"text":7851},"minecraft","Vollständige Anleitung zur Verknüpfung deines Minecraft-Servers mit KiroCloud und Discord.",{},"\u002Fdocs\u002Fde\u002Fminecraft-link",{"title":7333,"description":7960},"docs\u002Fde\u002Fminecraft-link","o_vT3IBLKv3fJ7bmbEctyevKmrCJ3RTdNvI1-LKDkIg",{"id":7967,"title":7968,"author":2000,"body":7969,"category":3703,"description":8507,"extension":549,"lastUpdated":2002,"meta":8508,"navigation":551,"order":763,"path":8509,"readTime":8510,"seo":8511,"stem":8512,"__hash__":8513},"docs\u002Fdocs\u002Fde\u002Fnodejs-gc-tuning.md","Node.js Garbage Collection Tuning für Bots im 24\u002F7 Dauerbetrieb",{"type":14,"value":7970,"toc":8496},[7971,7974,7981,7984,7986,7990,7993,8039,8045,8047,8051,8054,8061,8064,8084,8090,8097,8100,8116,8118,8122,8129,8398,8404,8406,8410,8417,8467,8493],[17,7972,7968],{"id":7973},"nodejs-garbage-collection-tuning-für-bots-im-247-dauerbetrieb",[22,7975,7976,7977,7980],{},"In vielen Discord-Bot-Umgebungen führt der standardmäßige Garbage-Collection-Zyklus von Node.js zu unvorhersehbaren Verzögerungen (GC-Pauses). Wenn die V8-Engine einen vollständigen Mark-Sweep-Compact-Durchlauf startet, stoppt der JavaScript-Event-Loop für mehrere Dutzend bis Hunderte Millisekunden. Für Discord-Bots bedeutet das: verpasste Heartbeats, steigender Gateway-Ping und im schlimmsten Fall Verbindungsabbrüche mit Code ",[97,7978,7979],{},"1006"," (Abnormal Closure).",[22,7982,7983],{},"In diesem Guide erklären wir die V8-Speicherarchitektur und wie du Node.js mit gezielten Flags für minimale Latenz und stabilen Dauerbetrieb konfigurierst.",[29,7985],{},[32,7987,7989],{"id":7988},"_1-v8-speicherarchitektur-new-space-vs-old-space","1. V8 Speicherarchitektur: New Space vs. Old Space",[22,7991,7992],{},"Der V8-Heap ist in zwei Hauptbereiche unterteilt:",[70,7994,7995,8019],{},[43,7996,7997,8000],{},[47,7998,7999],{},"Young Generation (New Space):",[40,8001,8002,8005,8012],{},[43,8003,8004],{},"Hier landen alle neu erstellten Objekte (Nachrichten, Events, Strings).",[43,8006,8007,8008,8011],{},"Der Bereich ist klein (typischerweise 16–64 MB) und wird extrem schnell mit dem ",[47,8009,8010],{},"Scavenger-Algorithmus"," bereinigt.",[43,8013,8014,8015,8018],{},"Objekte, die zwei Scavenge-Zyklen überleben, werden in den ",[292,8016,8017],{},"Old Space"," befördert.",[43,8020,8021,8024],{},[47,8022,8023],{},"Old Generation (Old Space):",[40,8025,8026,8029],{},[43,8027,8028],{},"Enthält langlebige Objekte (Bot-Client, Modul-Singletons, Langzeit-Caches).",[43,8030,8031,8032,186,8035,8038],{},"Die Bereinigung erfordert teure ",[47,8033,8034],{},"Mark-Sweep-",[47,8036,8037],{},"Mark-Compact-Zyklen",", die Stop-the-World Pausen verursachen.",[635,8040,8043],{"className":8041,"code":8042,"language":1053},[1051],"┌────────────────────────────────────────────────────────┐\n│                   V8 Process Memory                    │\n├──────────────────────────┬─────────────────────────────┤\n│  New Space (16-64 MB)    │   Old Space (up to max-old) │\n│  ┌────────────┬────────┐ │   ┌───────────────────────┐ │\n│  │ Semi-Space │ To-    │ │   │ Long-Lived Objects    │ │\n│  │ From-Space │ Space  │ │   │ Bot Client, Caches    │ │\n│  └────────────┴────────┘ │   └───────────────────────┘ │\n│      [Scavenge GC]       │      [Mark-Sweep-Compact]   │\n└──────────────────────────┴─────────────────────────────┘\n",[97,8044,8042],{"__ignoreMap":7},[29,8046],{},[32,8048,8050],{"id":8049},"_2-die-wichtigsten-v8-flags-für-discord-bots","2. Die wichtigsten V8 Flags für Discord-Bots",[22,8052,8053],{},"Beim Start deines Node.js-Prozesses kannst du das Verhalten des Garbage Collectors über Runtime-Flags steuern:",[714,8055,8057,8058],{"id":8056},"a-heap-limit-explizit-setzen-max-old-space-size","A. Heap-Limit explizit setzen: ",[97,8059,8060],{},"--max-old-space-size",[22,8062,8063],{},"Standardmäßig allokiert Node.js auf 64-Bit-Systemen bis zu 2 oder 4 GB Speicher, bevor aggressiv aufgeräumt wird. Für Bots führt dies dazu, dass Müll lange im RAM verbleibt:",[635,8065,8067],{"className":637,"code":8066,"language":639,"meta":7,"style":7},"# Auf einem Server mit 1 GB RAM-Zuweisung:\nnode --max-old-space-size=512 dist\u002Findex.js\n",[97,8068,8069,8074],{"__ignoreMap":7},[114,8070,8071],{"class":644,"line":552},[114,8072,8073],{"class":1142},"# Auf einem Server mit 1 GB RAM-Zuweisung:\n",[114,8075,8076,8078,8081],{"class":644,"line":537},[114,8077,5915],{"class":647},[114,8079,8080],{"class":651}," --max-old-space-size=512",[114,8082,8083],{"class":651}," dist\u002Findex.js\n",[22,8085,8086,8089],{},[292,8087,8088],{},"Effekt:"," V8 startet Aufräumzyklen deutlich früher, bevor das System in Swap-Memory gerät oder der Linux OOM-Killer den Prozess terminiert.",[714,8091,8093,8094],{"id":8092},"b-inkrementelles-paralleles-marking-max-semi-space-size","B. Inkrementelles & Paralleles Marking: ",[97,8095,8096],{},"--max-semi-space-size",[22,8098,8099],{},"Vergrößert den New-Space, sodass kurzlebige Objekte (wie Payload-Parsing von Discord-Nachrichten) komplett im schnellen New-Space abgeräumt werden, ohne jemals in den Old-Space zu wandern:",[635,8101,8103],{"className":637,"code":8102,"language":639,"meta":7,"style":7},"node --max-semi-space-size=64 --max-old-space-size=512 dist\u002Findex.js\n",[97,8104,8105],{"__ignoreMap":7},[114,8106,8107,8109,8112,8114],{"class":644,"line":552},[114,8108,5915],{"class":647},[114,8110,8111],{"class":651}," --max-semi-space-size=64",[114,8113,8080],{"class":651},[114,8115,8083],{"class":651},[29,8117],{},[32,8119,8121],{"id":8120},"_3-gc-metriken-im-laufenden-betrieb-protokollieren","3. GC-Metriken im laufenden Betrieb protokollieren",[22,8123,8124,8125,8128],{},"Mit dem nativen ",[97,8126,8127],{},"perf_hooks","-Modul von Node.js kannst du die genaue Dauer jeder GC-Pause in Mikrosekunden messen:",[635,8130,8132],{"className":1071,"code":8131,"language":1073,"meta":7,"style":7},"import { PerformanceObserver } from 'node:perf_hooks';\n\nexport function setupGCMonitoring() {\n  const obs = new PerformanceObserver((list) => {\n    const entries = list.getEntries();\n    for (const entry of entries) {\n      const durationMs = entry.duration;\n      \u002F\u002F entry.detail enthält den GC-Typ: 1 = Scavenge, 2 = Mark-Sweep-Compact, 4 = Incremental\n      if (durationMs > 25) {\n        console.warn(`[GC Warning] Lange GC-Pause erkannt: ${durationMs.toFixed(2)} ms (Typ: ${entry.name})`);\n      }\n    }\n  });\n\n  obs.observe({ entryTypes: ['gc'] });\n}\n",[97,8133,8134,8156,8160,8173,8199,8220,8241,8259,8264,8281,8335,8339,8343,8351,8355,8394],{"__ignoreMap":7},[114,8135,8136,8138,8140,8143,8145,8147,8149,8152,8154],{"class":644,"line":552},[114,8137,1081],{"class":1080},[114,8139,3035],{"class":735},[114,8141,8142],{"class":745}," PerformanceObserver",[114,8144,3050],{"class":735},[114,8146,3053],{"class":1080},[114,8148,1090],{"class":735},[114,8150,8151],{"class":651},"node:perf_hooks",[114,8153,1095],{"class":735},[114,8155,1098],{"class":735},[114,8157,8158],{"class":644,"line":537},[114,8159,856],{"emptyLinePlaceholder":551},[114,8161,8162,8164,8166,8169,8171],{"class":644,"line":763},[114,8163,1152],{"class":1080},[114,8165,1232],{"class":1107},[114,8167,8168],{"class":1235}," setupGCMonitoring",[114,8170,1532],{"class":735},[114,8172,1161],{"class":735},[114,8174,8175,8177,8180,8182,8184,8186,8188,8190,8193,8195,8197],{"class":644,"line":802},[114,8176,1270],{"class":1107},[114,8178,8179],{"class":745}," obs",[114,8181,1276],{"class":735},[114,8183,1339],{"class":735},[114,8185,8142],{"class":1235},[114,8187,1239],{"class":1166},[114,8189,1239],{"class":735},[114,8191,8192],{"class":1242},"list",[114,8194,1300],{"class":735},[114,8196,2478],{"class":1107},[114,8198,1161],{"class":735},[114,8200,8201,8203,8206,8208,8211,8213,8216,8218],{"class":644,"line":808},[114,8202,6505],{"class":1107},[114,8204,8205],{"class":745}," entries",[114,8207,1276],{"class":735},[114,8209,8210],{"class":745}," list",[114,8212,50],{"class":735},[114,8214,8215],{"class":1235},"getEntries",[114,8217,1532],{"class":1166},[114,8219,1098],{"class":735},[114,8221,8222,8225,8227,8229,8232,8235,8237,8239],{"class":644,"line":814},[114,8223,8224],{"class":1080},"    for",[114,8226,257],{"class":1166},[114,8228,1108],{"class":1107},[114,8230,8231],{"class":745}," entry",[114,8233,8234],{"class":735}," of",[114,8236,8205],{"class":745},[114,8238,1327],{"class":1166},[114,8240,1330],{"class":735},[114,8242,8243,8246,8248,8250,8252,8254,8257],{"class":644,"line":820},[114,8244,8245],{"class":1107},"      const",[114,8247,3540],{"class":745},[114,8249,1276],{"class":735},[114,8251,8231],{"class":745},[114,8253,50],{"class":735},[114,8255,8256],{"class":745},"duration",[114,8258,1098],{"class":735},[114,8260,8261],{"class":644,"line":826},[114,8262,8263],{"class":1142},"      \u002F\u002F entry.detail enthält den GC-Typ: 1 = Scavenge, 2 = Mark-Sweep-Compact, 4 = Incremental\n",[114,8265,8266,8268,8270,8273,8275,8277,8279],{"class":644,"line":832},[114,8267,4907],{"class":1080},[114,8269,257],{"class":1166},[114,8271,8272],{"class":745},"durationMs",[114,8274,5594],{"class":735},[114,8276,3169],{"class":1135},[114,8278,1327],{"class":1166},[114,8280,1330],{"class":735},[114,8282,8283,8285,8287,8289,8291,8293,8296,8298,8300,8302,8304,8306,8308,8310,8312,8315,8317,8320,8322,8325,8327,8329,8331,8333],{"class":644,"line":891},[114,8284,4971],{"class":745},[114,8286,50],{"class":735},[114,8288,4038],{"class":1235},[114,8290,1239],{"class":1166},[114,8292,2651],{"class":735},[114,8294,8295],{"class":651},"[GC Warning] Lange GC-Pause erkannt: ",[114,8297,2657],{"class":735},[114,8299,8272],{"class":745},[114,8301,50],{"class":735},[114,8303,2683],{"class":1235},[114,8305,1239],{"class":745},[114,8307,2688],{"class":1135},[114,8309,1300],{"class":745},[114,8311,2693],{"class":735},[114,8313,8314],{"class":651}," ms (Typ: ",[114,8316,2657],{"class":735},[114,8318,8319],{"class":745},"entry",[114,8321,50],{"class":735},[114,8323,8324],{"class":745},"name",[114,8326,2693],{"class":735},[114,8328,1300],{"class":651},[114,8330,2651],{"class":735},[114,8332,1300],{"class":1166},[114,8334,1098],{"class":735},[114,8336,8337],{"class":644,"line":1204},[114,8338,5071],{"class":735},[114,8340,8341],{"class":644,"line":1209},[114,8342,5076],{"class":735},[114,8344,8345,8347,8349],{"class":644,"line":1215},[114,8346,2498],{"class":735},[114,8348,1300],{"class":1166},[114,8350,1098],{"class":735},[114,8352,8353],{"class":644,"line":1221},[114,8354,856],{"emptyLinePlaceholder":551},[114,8356,8357,8360,8362,8365,8367,8370,8373,8375,8378,8380,8383,8385,8388,8390,8392],{"class":644,"line":1227},[114,8358,8359],{"class":745},"  obs",[114,8361,50],{"class":735},[114,8363,8364],{"class":1235},"observe",[114,8366,1239],{"class":1166},[114,8368,8369],{"class":735},"{",[114,8371,8372],{"class":1166}," entryTypes",[114,8374,1170],{"class":735},[114,8376,8377],{"class":1166}," [",[114,8379,1095],{"class":735},[114,8381,8382],{"class":651},"gc",[114,8384,1095],{"class":735},[114,8386,8387],{"class":1166},"] ",[114,8389,2693],{"class":735},[114,8391,1300],{"class":1166},[114,8393,1098],{"class":735},[114,8395,8396],{"class":644,"line":1267},[114,8397,879],{"class":735},[22,8399,8400,8401,8403],{},"Wenn du in den Logs regelmäßige Spitzen von über 50 ms siehst, bedeutet dies, dass zu viele temporäre Objekte in den ",[292,8402,8017],{}," befördert werden.",[29,8405],{},[32,8407,8409],{"id":8408},"_4-empfohlene-produktions-startparameter","4. Empfohlene Produktions-Startparameter",[22,8411,8412,8413,8416],{},"Für Container- und Cloud-Deployments auf KiroCloud empfehlen wir folgende Kombination im ",[97,8414,8415],{},"package.json"," Startskript:",[635,8418,8420],{"className":7609,"code":8419,"language":7611,"meta":7,"style":7},"{\n  \"scripts\": {\n    \"start:prod\": \"node --max-semi-space-size=64 --max-old-space-size=768 --enable-source-maps dist\u002Findex.js\"\n  }\n}\n",[97,8421,8422,8426,8440,8459,8463],{"__ignoreMap":7},[114,8423,8424],{"class":644,"line":552},[114,8425,1330],{"class":735},[114,8427,8428,8431,8434,8436,8438],{"class":644,"line":537},[114,8429,8430],{"class":735},"  \"",[114,8432,8433],{"class":1107},"scripts",[114,8435,742],{"class":735},[114,8437,1170],{"class":735},[114,8439,1161],{"class":735},[114,8441,8442,8445,8448,8450,8452,8454,8457],{"class":644,"line":763},[114,8443,8444],{"class":735},"    \"",[114,8446,8447],{"class":647},"start:prod",[114,8449,742],{"class":735},[114,8451,1170],{"class":735},[114,8453,736],{"class":735},[114,8455,8456],{"class":651},"node --max-semi-space-size=64 --max-old-space-size=768 --enable-source-maps dist\u002Findex.js",[114,8458,773],{"class":735},[114,8460,8461],{"class":644,"line":802},[114,8462,817],{"class":735},[114,8464,8465],{"class":644,"line":808},[114,8466,879],{"class":735},[40,8468,8469,8477,8485],{},[43,8470,8471,8476],{},[47,8472,8473],{},[97,8474,8475],{},"--max-semi-space-size=64",": Hält JSON-WebSocket-Payloads im schnellen Young-Space.",[43,8478,8479,8484],{},[47,8480,8481],{},[97,8482,8483],{},"--max-old-space-size=768",": Verhindert, dass der Prozess das 1-GB-Containerlimit überschreitet.",[43,8486,8487,8492],{},[47,8488,8489],{},[97,8490,8491],{},"--enable-source-maps",": Präzise Stack-Traces bei Fehlern ohne Performance-Verlust.",[944,8494,8495],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":7,"searchDepth":537,"depth":537,"links":8497},[8498,8499,8505,8506],{"id":7988,"depth":537,"text":7989},{"id":8049,"depth":537,"text":8050,"children":8500},[8501,8503],{"id":8056,"depth":763,"text":8502},"A. Heap-Limit explizit setzen: --max-old-space-size",{"id":8092,"depth":763,"text":8504},"B. Inkrementelles & Paralleles Marking: --max-semi-space-size",{"id":8120,"depth":537,"text":8121},{"id":8408,"depth":537,"text":8409},"Tiefgehende Optimierung der V8-Engine für Node.js Cloud-Bots. Scavenge vs. Mark-Sweep, Heap-Limits, GC-Flags und Latenzreduktion.",{},"\u002Fdocs\u002Fde\u002Fnodejs-gc-tuning","11 min",{"title":7968,"description":8507},"docs\u002Fde\u002Fnodejs-gc-tuning","Gum8zOayrLqzwLvsVkVJKtylMmxiOij8pRFDUIxkF-Y",{"id":8515,"title":8516,"author":12,"body":8517,"category":6873,"description":8662,"extension":549,"lastUpdated":12,"meta":8663,"navigation":551,"order":1209,"path":8664,"readTime":12,"seo":8665,"stem":8666,"__hash__":8667},"docs\u002Fdocs\u002Fde\u002Fpull-system.md","Discord Community-Join & OAuth2",{"type":14,"value":8518,"toc":8656},[8519,8523,8526,8528,8532,8535,8560,8567,8569,8573,8576,8587,8589,8593,8596,8632,8634,8638,8644],[17,8520,8522],{"id":8521},"discord-community-join-oauth2-integration","Discord Community-Join & OAuth2 Integration",[22,8524,8525],{},"KiroCloud nutzt das offizielle Discord OAuth2-Protokoll für die passwortlose Authentifizierung und direkte Verknüpfung von Discord-Benutzerkonten mit der KiroCloud-Plattform.",[29,8527],{},[32,8529,8531],{"id":8530},"_1-wie-funktioniert-die-discord-autorisierung","1. Wie funktioniert die Discord-Autorisierung?",[22,8533,8534],{},"Wenn du dich auf KiroCloud anmeldest, wirst du zu der offiziellen Autorisierungsseite von Discord weitergeleitet. Dort siehst du transparent alle angeforderten Berechtigungen (Scopes):",[40,8536,8537,8543,8549,8554],{},[43,8538,8539,8542],{},[97,8540,8541],{},"identify",": Erlaubt KiroCloud, deinen Benutzernamen und deinen Avatar im Dashboard anzuzeigen.",[43,8544,8545,8548],{},[97,8546,8547],{},"email",": Erlaubt das Senden wichtiger Systembenachrichtigungen (z. B. 2FA-Wiederherstellung oder Wartungsankündigungen).",[43,8550,8551,8553],{},[97,8552,4423],{},": Ermöglicht das Auflisten der Discord-Server, auf denen du Administratorrechte besitzt, damit du deine Bots direkt dort einladen und konfigurieren kannst.",[43,8555,8556,8559],{},[97,8557,8558],{},"guilds.join"," (Optionaler Community-Beitritt): Ermöglicht den direkten Beitritt zu unserem offiziellen KiroCloud Community- und Support-Server.",[109,8561,8562],{},[22,8563,8564,8566],{},[114,8565,2184],{},"\nKiroCloud hat zu keinem Zeitpunkt Zugriff auf dein Discord-Passwort oder deine privaten Nachrichten. Sämtliche Kommunikation erfolgt über standardisierte, zeitlich begrenzte OAuth2-Tokens.",[29,8568],{},[32,8570,8572],{"id":8571},"_2-der-community-beitritt-opt-in","2. Der Community-Beitritt (Opt-In)",[22,8574,8575],{},"Um Support-Anfragen schnell bearbeiten zu können und Community-Mitgliedern direkten Zugriff auf Ankündigungen zu geben, bietet KiroCloud einen automatisierten Beitritt zum offiziellen KiroCloud-Server an:",[70,8577,8578,8581,8584],{},[43,8579,8580],{},"Beim Login wird der Nutzer gefragt, ob er der offiziellen KiroCloud Support-Community beitreten möchte.",[43,8582,8583],{},"Nach der Zustimmung wird der Nutzer automatisch dem Community-Server hinzugefügt.",[43,8585,8586],{},"Nutzer können den Server jederzeit eigenständig wieder verlassen, ohne dass dies Auswirkungen auf ihr KiroCloud-Konto hat.",[29,8588],{},[32,8590,8592],{"id":8591},"_3-datenschutz-token-sicherheit-aes-256-gcm","3. Datenschutz & Token-Sicherheit (AES-256-GCM)",[22,8594,8595],{},"Die Sicherheit deiner Zugangsdaten steht an oberster Stelle:",[40,8597,8598,8607,8613,8626],{},[43,8599,8600,8603,8604,8606],{},[47,8601,8602],{},"Strikte Verschlüsselung:"," Alle OAuth2-Tokens werden in unserer Datenbank mit ",[47,8605,1028],{}," und einem hardware-gesicherten Serverschlüssel verschlüsselt gespeichert.",[43,8608,8609,8612],{},[47,8610,8611],{},"Keine Weitergabe an Dritte:"," Deine Autorisierungstokens werden ausschließlich für KiroCloud-eigene Funktionen verwendet und niemals an Dritte weitergegeben oder für fremde Server genutzt.",[43,8614,8615,8618,8619],{},[47,8616,8617],{},"Volle Kontrolle (Widerruf):"," Du kannst die Berechtigung von KiroCloud jederzeit mit einem Klick in deinen Discord-Einstellungen widerrufen:\n",[40,8620,8621],{},[43,8622,8623,50],{},[292,8624,8625],{},"Discord Benutzereinstellungen > Autorisierte Apps > KiroCloud > Autorisierung aufheben",[43,8627,8628,8631],{},[47,8629,8630],{},"DSGVO-Rechte:"," Wenn du deinen KiroCloud-Account in den Dashboard-Einstellungen löschst, werden sämtliche gespeicherten Tokens und Authentifizierungsdaten unwiderruflich aus der Datenbank gelöscht.",[29,8633],{},[32,8635,8637],{"id":8636},"_4-einhaltung-der-discord-developer-richtlinien","4. Einhaltung der Discord Developer Richtlinien",[22,8639,8640,8641,1170],{},"KiroCloud hält sich strikt an die ",[47,8642,8643],{},"Discord Developer Terms of Service and Developer Policy",[40,8645,8646,8653],{},[43,8647,8648,8649,8652],{},"Es finden ",[47,8650,8651],{},"keine unerlaubten Massenbeitritte"," oder unberechtigte Weiterleitungen auf Server Dritter statt.",[43,8654,8655],{},"Der Beitritt erfolgt ausschließlich transparent und zweckgebunden für den offiziellen KiroCloud-Dienst.",{"title":7,"searchDepth":537,"depth":537,"links":8657},[8658,8659,8660,8661],{"id":8530,"depth":537,"text":8531},{"id":8571,"depth":537,"text":8572},{"id":8591,"depth":537,"text":8592},{"id":8636,"depth":537,"text":8637},"Transparente Erklärung der Discord OAuth2 Integration und des Community-Beitritts",{},"\u002Fdocs\u002Fde\u002Fpull-system",{"title":8516,"description":8662},"docs\u002Fde\u002Fpull-system","GFYW6ofAbs7jDneGkOBfuahLU7N_b3tZOhQBo9fYZ7o",{"id":8669,"title":969,"author":12,"body":8670,"category":12,"description":9707,"extension":549,"lastUpdated":12,"meta":9708,"navigation":551,"order":962,"path":9709,"readTime":12,"seo":9710,"stem":9714,"__hash__":9715},"docs\u002Fdocs\u002Fde\u002Frcon-security-hardening.md",{"type":14,"value":8671,"toc":9699},[8672,8676,8692,8695,8697,8701,8704,8728,8730,8734,8737,8743,8745,8749,8752,9467,9469,9475,9478,9537,9539,9543,9550,9693,9696],[17,8673,8675],{"id":8674},"minecraft-rcon-protokoll-absicherung-socket-hardening-anti-brute-force","Minecraft RCON Protokoll Absicherung: Socket-Hardening & Anti-Brute-Force",[22,8677,2016,8678,8681,8682,381,8685,381,8688,8691],{},[47,8679,8680],{},"Remote Console (RCON)"," Protokoll von Minecraft ermöglicht die Ausführung beliebiger Server-Befehle über eine TCP-Verbindung. Ein Angreifer, der ein RCON-Passwort knackt, erhält uneingeschränkte Administrator-Rechte auf dem Server (",[97,8683,8684],{},"op",[97,8686,8687],{},"stop",[97,8689,8690],{},"whitelist off",", Ausführung von NBT-Befehlen). Da das originale Source-RCON-Protokoll aus dem Jahr 2004 stammt und von Haus aus weder Verschlüsselung noch Brute-Force-Schutz bietet, erfordert der Betrieb im Internet strikte Sicherheitsmaßnahmen.",[22,8693,8694],{},"In dieser Anleitung analysieren wir typische RCON-Angriffsvektoren und demonstrieren, wie wir die Minecraft Cloud Bridge auf KiroCloud gegen Angriffe absichern.",[29,8696],{},[32,8698,8700],{"id":8699},"_1-schwachstellen-des-nativen-rcon-protokolls","1. Schwachstellen des nativen RCON-Protokolls",[22,8702,8703],{},"Das Standard-RCON-Protokoll von Minecraft Vanilla und PaperMC weist gravierende Schwachstellen auf:",[70,8705,8706,8716,8722],{},[43,8707,8708,8711,8712,8715],{},[47,8709,8710],{},"Keine Transportverschlüsselung:"," Passwörter und Konsolenausgaben werden im Klartext über TCP übertragen. In unverschlüsselten Netzwerken können sie per Paket-Sniffing (",[97,8713,8714],{},"tcpdump",", Wireshark) mitgelesen werden.",[43,8717,8718,8721],{},[47,8719,8720],{},"Fehlendes Rate-Limiting:"," Der Minecraft-Server begrenzt fehlgeschlagene Login-Versuche nicht. Angreifer können Tausende Passwörter pro Sekunde ausprobieren, ohne gesperrt zu werden.",[43,8723,8724,8727],{},[47,8725,8726],{},"Pufferüberläufe & Single-Threaded Bottlenecks:"," Ein TCP-SYN-Flood oder das Senden von Paketen mit manipulierter Längenangabe kann den Haupt-Server-Thread blockieren und TPS-Einbrüche verursachen.",[29,8729],{},[32,8731,8733],{"id":8732},"_2-architektonische-schutzschichten","2. Architektonische Schutzschichten",[22,8735,8736],{},"Um diese Risiken zu eliminieren, darf der RCON-Port niemals direkt im öffentlichen Internet erreichbar sein. Auf KiroCloud wird folgende Architektur erzwungen:",[635,8738,8741],{"className":8739,"code":8740,"language":1053},[1051],"┌────────────────────────────────┐\n│   KiroCloud Dashboard Server   │\n└───────────────┬────────────────┘\n                │ TLS-gesicherter interner Tunnel (WireGuard \u002F VPN)\n                ▼\n┌────────────────────────────────┐\n│  Reverse Proxy \u002F RCON Gateway  │ ◄─── Fail2ban \u002F IP Whitelist\n└───────────────┬────────────────┘\n                │ Loopback Socket (127.0.0.1:25575)\n                ▼\n┌────────────────────────────────┐\n│    Minecraft Server Prozess    │\n└────────────────────────────────┘\n",[97,8742,8740],{"__ignoreMap":7},[29,8744],{},[32,8746,8748],{"id":8747},"_3-implementierung-eines-anti-brute-force-proxys-mit-nodejs","3. Implementierung eines Anti-Brute-Force Proxys mit Node.js",[22,8750,8751],{},"Wenn du eine externe Bridge für RCON betreibst, fange fehlgeschlagene Login-Versuche mit einer Token-Bucket-Rate-Limitierung ab:",[635,8753,8755],{"className":1071,"code":8754,"language":1073,"meta":7,"style":7},"import net from 'node:net';\n\ninterface FailedAttempt {\n  count: number;\n  blockedUntil: number;\n}\n\nconst failedLogins = new Map\u003Cstring, FailedAttempt>();\nconst MAX_ATTEMPTS = 5;\nconst LOCKOUT_MS = 15 * 60 * 1000; \u002F\u002F 15 Minuten Sperre\n\nexport function createProtectedRconClient(host: string, port: number, clientIp: string) {\n  const now = Date.now();\n  const state = failedLogins.get(clientIp);\n\n  if (state && state.blockedUntil > now) {\n    const remainingSec = Math.ceil((state.blockedUntil - now) \u002F 1000);\n    throw new Error(`IP ${clientIp} ist wegen zu vieler Fehlversuche für noch ${remainingSec}s gesperrt.`);\n  }\n\n  const socket = new net.Socket();\n  socket.connect(port, host);\n\n  \u002F\u002F Authentifizierungslogik & Paketverarbeitung\n  socket.on('data', (data) => {\n    \u002F\u002F Bei RCON gibt Type 2 (SERVERDATA_AUTH_RESPONSE) mit ID -1 einen Fehlschlag an\n    const responseId = data.readInt32LE(4);\n    if (responseId === -1) {\n      const attempts = (state?.count ?? 0) + 1;\n      console.warn(`[RCON Security] Fehlgeschlagener RCON-Login von ${clientIp} (Versuch ${attempts}\u002F${MAX_ATTEMPTS})`);\n\n      if (attempts >= MAX_ATTEMPTS) {\n        failedLogins.set(clientIp, { count: attempts, blockedUntil: now + LOCKOUT_MS });\n        socket.destroy();\n      } else {\n        failedLogins.set(clientIp, { count: attempts, blockedUntil: 0 });\n      }\n    }\n  });\n\n  return socket;\n}\n",[97,8756,8757,8775,8779,8789,8800,8811,8815,8819,8848,8862,8889,8893,8933,8952,8978,8982,9009,9049,9089,9093,9097,9120,9144,9148,9153,9181,9186,9211,9232,9262,9311,9315,9333,9377,9391,9399,9435,9439,9443,9451,9455,9463],{"__ignoreMap":7},[114,8758,8759,8761,8764,8766,8768,8771,8773],{"class":644,"line":552},[114,8760,1081],{"class":1080},[114,8762,8763],{"class":745}," net ",[114,8765,1087],{"class":1080},[114,8767,1090],{"class":735},[114,8769,8770],{"class":651},"node:net",[114,8772,1095],{"class":735},[114,8774,1098],{"class":735},[114,8776,8777],{"class":644,"line":537},[114,8778,856],{"emptyLinePlaceholder":551},[114,8780,8781,8784,8787],{"class":644,"line":763},[114,8782,8783],{"class":1107},"interface",[114,8785,8786],{"class":647}," FailedAttempt",[114,8788,1161],{"class":735},[114,8790,8791,8794,8796,8798],{"class":644,"line":802},[114,8792,8793],{"class":1166},"  count",[114,8795,1170],{"class":735},[114,8797,3506],{"class":647},[114,8799,1098],{"class":735},[114,8801,8802,8805,8807,8809],{"class":644,"line":808},[114,8803,8804],{"class":1166},"  blockedUntil",[114,8806,1170],{"class":735},[114,8808,3506],{"class":647},[114,8810,1098],{"class":735},[114,8812,8813],{"class":644,"line":814},[114,8814,879],{"class":735},[114,8816,8817],{"class":644,"line":820},[114,8818,856],{"emptyLinePlaceholder":551},[114,8820,8821,8823,8826,8828,8830,8833,8835,8838,8840,8842,8844,8846],{"class":644,"line":826},[114,8822,1108],{"class":1107},[114,8824,8825],{"class":745}," failedLogins ",[114,8827,1114],{"class":735},[114,8829,1339],{"class":735},[114,8831,8832],{"class":1235}," Map",[114,8834,3499],{"class":735},[114,8836,8837],{"class":647},"string",[114,8839,1250],{"class":735},[114,8841,8786],{"class":647},[114,8843,3509],{"class":735},[114,8845,1532],{"class":745},[114,8847,1098],{"class":735},[114,8849,8850,8852,8855,8857,8860],{"class":644,"line":832},[114,8851,1108],{"class":1107},[114,8853,8854],{"class":745}," MAX_ATTEMPTS ",[114,8856,1114],{"class":735},[114,8858,8859],{"class":1135}," 5",[114,8861,1098],{"class":735},[114,8863,8864,8866,8869,8871,8874,8877,8880,8882,8884,8886],{"class":644,"line":891},[114,8865,1108],{"class":1107},[114,8867,8868],{"class":745}," LOCKOUT_MS ",[114,8870,1114],{"class":735},[114,8872,8873],{"class":1135}," 15",[114,8875,8876],{"class":735}," *",[114,8878,8879],{"class":1135}," 60",[114,8881,8876],{"class":735},[114,8883,4964],{"class":1135},[114,8885,1139],{"class":735},[114,8887,8888],{"class":1142}," \u002F\u002F 15 Minuten Sperre\n",[114,8890,8891],{"class":644,"line":1204},[114,8892,856],{"emptyLinePlaceholder":551},[114,8894,8895,8897,8899,8902,8904,8907,8909,8911,8913,8916,8918,8920,8922,8925,8927,8929,8931],{"class":644,"line":1209},[114,8896,1152],{"class":1080},[114,8898,1232],{"class":1107},[114,8900,8901],{"class":1235}," createProtectedRconClient",[114,8903,1239],{"class":735},[114,8905,8906],{"class":1242},"host",[114,8908,1170],{"class":735},[114,8910,1173],{"class":647},[114,8912,1250],{"class":735},[114,8914,8915],{"class":1242}," port",[114,8917,1170],{"class":735},[114,8919,3506],{"class":647},[114,8921,1250],{"class":735},[114,8923,8924],{"class":1242}," clientIp",[114,8926,1170],{"class":735},[114,8928,1173],{"class":647},[114,8930,1300],{"class":735},[114,8932,1161],{"class":735},[114,8934,8935,8937,8940,8942,8944,8946,8948,8950],{"class":644,"line":1215},[114,8936,1270],{"class":1107},[114,8938,8939],{"class":745}," now",[114,8941,1276],{"class":735},[114,8943,3567],{"class":745},[114,8945,50],{"class":735},[114,8947,2796],{"class":1235},[114,8949,1532],{"class":1166},[114,8951,1098],{"class":735},[114,8953,8954,8956,8959,8961,8964,8966,8969,8971,8974,8976],{"class":644,"line":1221},[114,8955,1270],{"class":1107},[114,8957,8958],{"class":745}," state",[114,8960,1276],{"class":735},[114,8962,8963],{"class":745}," failedLogins",[114,8965,50],{"class":735},[114,8967,8968],{"class":1235},"get",[114,8970,1239],{"class":1166},[114,8972,8973],{"class":745},"clientIp",[114,8975,1300],{"class":1166},[114,8977,1098],{"class":735},[114,8979,8980],{"class":644,"line":1227},[114,8981,856],{"emptyLinePlaceholder":551},[114,8983,8984,8986,8988,8991,8994,8996,8998,9001,9003,9005,9007],{"class":644,"line":1267},[114,8985,1308],{"class":1080},[114,8987,257],{"class":1166},[114,8989,8990],{"class":745},"state",[114,8992,8993],{"class":735}," &&",[114,8995,8958],{"class":745},[114,8997,50],{"class":735},[114,8999,9000],{"class":745},"blockedUntil",[114,9002,5594],{"class":735},[114,9004,8939],{"class":745},[114,9006,1327],{"class":1166},[114,9008,1330],{"class":735},[114,9010,9011,9013,9016,9018,9020,9022,9025,9028,9030,9032,9034,9037,9039,9041,9043,9045,9047],{"class":644,"line":1305},[114,9012,6505],{"class":1107},[114,9014,9015],{"class":745}," remainingSec",[114,9017,1276],{"class":735},[114,9019,4640],{"class":745},[114,9021,50],{"class":735},[114,9023,9024],{"class":1235},"ceil",[114,9026,9027],{"class":1166},"((",[114,9029,8990],{"class":745},[114,9031,50],{"class":735},[114,9033,9000],{"class":745},[114,9035,9036],{"class":735}," -",[114,9038,8939],{"class":745},[114,9040,1327],{"class":1166},[114,9042,2668],{"class":735},[114,9044,4964],{"class":1135},[114,9046,1300],{"class":1166},[114,9048,1098],{"class":735},[114,9050,9051,9053,9055,9057,9059,9061,9064,9066,9068,9070,9073,9075,9078,9080,9083,9085,9087],{"class":644,"line":1333},[114,9052,1336],{"class":1080},[114,9054,1339],{"class":735},[114,9056,1342],{"class":1235},[114,9058,1239],{"class":1166},[114,9060,2651],{"class":735},[114,9062,9063],{"class":651},"IP ",[114,9065,2657],{"class":735},[114,9067,8973],{"class":745},[114,9069,2693],{"class":735},[114,9071,9072],{"class":651}," ist wegen zu vieler Fehlversuche für noch ",[114,9074,2657],{"class":735},[114,9076,9077],{"class":745},"remainingSec",[114,9079,2693],{"class":735},[114,9081,9082],{"class":651},"s gesperrt.",[114,9084,2651],{"class":735},[114,9086,1300],{"class":1166},[114,9088,1098],{"class":735},[114,9090,9091],{"class":644,"line":1358},[114,9092,817],{"class":735},[114,9094,9095],{"class":644,"line":1363},[114,9096,856],{"emptyLinePlaceholder":551},[114,9098,9099,9101,9104,9106,9108,9111,9113,9116,9118],{"class":644,"line":1368},[114,9100,1270],{"class":1107},[114,9102,9103],{"class":745}," socket",[114,9105,1276],{"class":735},[114,9107,1339],{"class":735},[114,9109,9110],{"class":745}," net",[114,9112,50],{"class":735},[114,9114,9115],{"class":1235},"Socket",[114,9117,1532],{"class":1166},[114,9119,1098],{"class":735},[114,9121,9122,9125,9127,9130,9132,9135,9137,9140,9142],{"class":644,"line":1374},[114,9123,9124],{"class":745},"  socket",[114,9126,50],{"class":735},[114,9128,9129],{"class":1235},"connect",[114,9131,1239],{"class":1166},[114,9133,9134],{"class":745},"port",[114,9136,1250],{"class":735},[114,9138,9139],{"class":745}," host",[114,9141,1300],{"class":1166},[114,9143,1098],{"class":735},[114,9145,9146],{"class":644,"line":1401},[114,9147,856],{"emptyLinePlaceholder":551},[114,9149,9150],{"class":644,"line":1435},[114,9151,9152],{"class":1142},"  \u002F\u002F Authentifizierungslogik & Paketverarbeitung\n",[114,9154,9155,9157,9159,9161,9163,9165,9167,9169,9171,9173,9175,9177,9179],{"class":644,"line":1440},[114,9156,9124],{"class":745},[114,9158,50],{"class":735},[114,9160,2457],{"class":1235},[114,9162,1239],{"class":1166},[114,9164,1095],{"class":735},[114,9166,6550],{"class":651},[114,9168,1095],{"class":735},[114,9170,1250],{"class":735},[114,9172,257],{"class":735},[114,9174,6550],{"class":1242},[114,9176,1300],{"class":735},[114,9178,2478],{"class":1107},[114,9180,1161],{"class":735},[114,9182,9183],{"class":644,"line":1483},[114,9184,9185],{"class":1142},"    \u002F\u002F Bei RCON gibt Type 2 (SERVERDATA_AUTH_RESPONSE) mit ID -1 einen Fehlschlag an\n",[114,9187,9188,9190,9193,9195,9197,9199,9202,9204,9207,9209],{"class":644,"line":1510},[114,9189,6505],{"class":1107},[114,9191,9192],{"class":745}," responseId",[114,9194,1276],{"class":735},[114,9196,6508],{"class":745},[114,9198,50],{"class":735},[114,9200,9201],{"class":1235},"readInt32LE",[114,9203,1239],{"class":1166},[114,9205,9206],{"class":1135},"4",[114,9208,1300],{"class":1166},[114,9210,1098],{"class":735},[114,9212,9213,9216,9218,9221,9223,9225,9228,9230],{"class":644,"line":1515},[114,9214,9215],{"class":1080},"    if",[114,9217,257],{"class":1166},[114,9219,9220],{"class":745},"responseId",[114,9222,4919],{"class":735},[114,9224,9036],{"class":735},[114,9226,9227],{"class":1135},"1",[114,9229,1327],{"class":1166},[114,9231,1330],{"class":735},[114,9233,9234,9236,9239,9241,9243,9245,9247,9250,9252,9254,9256,9258,9260],{"class":644,"line":1552},[114,9235,8245],{"class":1107},[114,9237,9238],{"class":745}," attempts",[114,9240,1276],{"class":735},[114,9242,257],{"class":1166},[114,9244,8990],{"class":745},[114,9246,3268],{"class":735},[114,9248,9249],{"class":745},"count",[114,9251,4953],{"class":735},[114,9253,3186],{"class":1135},[114,9255,1327],{"class":1166},[114,9257,260],{"class":735},[114,9259,4956],{"class":1135},[114,9261,1098],{"class":735},[114,9263,9264,9267,9269,9271,9273,9275,9278,9280,9282,9284,9287,9289,9292,9294,9296,9298,9301,9303,9305,9307,9309],{"class":644,"line":1557},[114,9265,9266],{"class":745},"      console",[114,9268,50],{"class":735},[114,9270,4038],{"class":1235},[114,9272,1239],{"class":1166},[114,9274,2651],{"class":735},[114,9276,9277],{"class":651},"[RCON Security] Fehlgeschlagener RCON-Login von ",[114,9279,2657],{"class":735},[114,9281,8973],{"class":745},[114,9283,2693],{"class":735},[114,9285,9286],{"class":651}," (Versuch ",[114,9288,2657],{"class":735},[114,9290,9291],{"class":745},"attempts",[114,9293,2693],{"class":735},[114,9295,2668],{"class":651},[114,9297,2657],{"class":735},[114,9299,9300],{"class":745},"MAX_ATTEMPTS",[114,9302,2693],{"class":735},[114,9304,1300],{"class":651},[114,9306,2651],{"class":735},[114,9308,1300],{"class":1166},[114,9310,1098],{"class":735},[114,9312,9313],{"class":644,"line":1565},[114,9314,856],{"emptyLinePlaceholder":551},[114,9316,9317,9319,9321,9323,9326,9329,9331],{"class":644,"line":1574},[114,9318,4907],{"class":1080},[114,9320,257],{"class":1166},[114,9322,9291],{"class":745},[114,9324,9325],{"class":735}," >=",[114,9327,9328],{"class":745}," MAX_ATTEMPTS",[114,9330,1327],{"class":1166},[114,9332,1330],{"class":735},[114,9334,9335,9338,9340,9342,9344,9346,9348,9350,9353,9355,9357,9359,9362,9364,9366,9368,9371,9373,9375],{"class":644,"line":1600},[114,9336,9337],{"class":745},"        failedLogins",[114,9339,50],{"class":735},[114,9341,3558],{"class":1235},[114,9343,1239],{"class":1166},[114,9345,8973],{"class":745},[114,9347,1250],{"class":735},[114,9349,3035],{"class":735},[114,9351,9352],{"class":1166}," count",[114,9354,1170],{"class":735},[114,9356,9238],{"class":745},[114,9358,1250],{"class":735},[114,9360,9361],{"class":1166}," blockedUntil",[114,9363,1170],{"class":735},[114,9365,8939],{"class":745},[114,9367,4479],{"class":735},[114,9369,9370],{"class":745}," LOCKOUT_MS",[114,9372,3050],{"class":735},[114,9374,1300],{"class":1166},[114,9376,1098],{"class":735},[114,9378,9379,9382,9384,9387,9389],{"class":644,"line":1608},[114,9380,9381],{"class":745},"        socket",[114,9383,50],{"class":735},[114,9385,9386],{"class":1235},"destroy",[114,9388,1532],{"class":1166},[114,9390,1098],{"class":735},[114,9392,9393,9395,9397],{"class":644,"line":1614},[114,9394,5051],{"class":735},[114,9396,5054],{"class":1080},[114,9398,1161],{"class":735},[114,9400,9401,9403,9405,9407,9409,9411,9413,9415,9417,9419,9421,9423,9425,9427,9429,9431,9433],{"class":644,"line":1619},[114,9402,9337],{"class":745},[114,9404,50],{"class":735},[114,9406,3558],{"class":1235},[114,9408,1239],{"class":1166},[114,9410,8973],{"class":745},[114,9412,1250],{"class":735},[114,9414,3035],{"class":735},[114,9416,9352],{"class":1166},[114,9418,1170],{"class":735},[114,9420,9238],{"class":745},[114,9422,1250],{"class":735},[114,9424,9361],{"class":1166},[114,9426,1170],{"class":735},[114,9428,3186],{"class":1135},[114,9430,3050],{"class":735},[114,9432,1300],{"class":1166},[114,9434,1098],{"class":735},[114,9436,9437],{"class":644,"line":1624},[114,9438,5071],{"class":735},[114,9440,9441],{"class":644,"line":1629},[114,9442,5076],{"class":735},[114,9444,9445,9447,9449],{"class":644,"line":1635},[114,9446,2498],{"class":735},[114,9448,1300],{"class":1166},[114,9450,1098],{"class":735},[114,9452,9453],{"class":644,"line":1640},[114,9454,856],{"emptyLinePlaceholder":551},[114,9456,9457,9459,9461],{"class":644,"line":1673},[114,9458,1560],{"class":1080},[114,9460,9103],{"class":745},[114,9462,1098],{"class":735},[114,9464,9465],{"class":644,"line":1704},[114,9466,879],{"class":735},[29,9468],{},[32,9470,9472,9473],{"id":9471},"_4-server-konfiguration-best-practices-in-serverproperties","4. Server-Konfiguration: Best Practices in ",[97,9474,7358],{},[22,9476,9477],{},"Konfiguriere deinen Minecraft-Server nach folgenden Regeln:",[635,9479,9481],{"className":7368,"code":9480,"language":7370,"meta":7,"style":7},"# RCON aktivieren\nenable-rcon=true\n\n# Port niemals auf 0.0.0.0 binden, sondern nur auf localhost\nrcon.port=25575\nserver-ip=127.0.0.1\n\n# Starkes, kryptografisch zufälliges Passwort (mindestens 32 Zeichen, z. B. via: openssl rand -base64 24)\nrcon.password=DEIN_SICHERES_32_STELLIGES_PASSWORT\n\n# Broadcast-Nachrichten an OPs einschränken\nbroadcast-rcon-to-ops=false\n",[97,9482,9483,9488,9492,9496,9501,9505,9510,9514,9519,9524,9528,9533],{"__ignoreMap":7},[114,9484,9485],{"class":644,"line":552},[114,9486,9487],{},"# RCON aktivieren\n",[114,9489,9490],{"class":644,"line":537},[114,9491,7377],{},[114,9493,9494],{"class":644,"line":763},[114,9495,856],{"emptyLinePlaceholder":551},[114,9497,9498],{"class":644,"line":802},[114,9499,9500],{},"# Port niemals auf 0.0.0.0 binden, sondern nur auf localhost\n",[114,9502,9503],{"class":644,"line":808},[114,9504,7382],{},[114,9506,9507],{"class":644,"line":814},[114,9508,9509],{},"server-ip=127.0.0.1\n",[114,9511,9512],{"class":644,"line":820},[114,9513,856],{"emptyLinePlaceholder":551},[114,9515,9516],{"class":644,"line":826},[114,9517,9518],{},"# Starkes, kryptografisch zufälliges Passwort (mindestens 32 Zeichen, z. B. via: openssl rand -base64 24)\n",[114,9520,9521],{"class":644,"line":832},[114,9522,9523],{},"rcon.password=DEIN_SICHERES_32_STELLIGES_PASSWORT\n",[114,9525,9526],{"class":644,"line":891},[114,9527,856],{"emptyLinePlaceholder":551},[114,9529,9530],{"class":644,"line":1204},[114,9531,9532],{},"# Broadcast-Nachrichten an OPs einschränken\n",[114,9534,9535],{"class":644,"line":1209},[114,9536,7392],{},[29,9538],{},[32,9540,9542],{"id":9541},"_5-befehls-sanitisierung-gegen-command-injection","5. Befehls-Sanitisierung gegen Command-Injection",[22,9544,9545,9546,9549],{},"Wenn dein Discord-Bot RCON-Befehle aus Nutzeingaben generiert (z. B. ",[97,9547,9548],{},"\u002Fwhitelist add [Name]","), musst du Eingaben strikt validieren:",[635,9551,9553],{"className":1071,"code":9552,"language":1073,"meta":7,"style":7},"\u002F\u002F GEFÄHRLICH: Angreifer könnte 'luca\\nop luca' übergeben!\nconst badCommand = `whitelist add ${userInput}`;\n\n\u002F\u002F SICHER: Nur alphanumerische Zeichen und Unterstriche erlauben\nexport function sanitizePlayerName(name: string): string {\n  if (!\u002F^[a-zA-Z0-9_]{3,16}$\u002F.test(name)) {\n    throw new Error('Ungültiger Spielername (nur 3-16 Buchstaben, Zahlen und Unterstriche erlaubt).');\n  }\n  return name;\n}\n",[97,9554,9555,9560,9582,9586,9591,9614,9655,9676,9680,9689],{"__ignoreMap":7},[114,9556,9557],{"class":644,"line":552},[114,9558,9559],{"class":1142},"\u002F\u002F GEFÄHRLICH: Angreifer könnte 'luca\\nop luca' übergeben!\n",[114,9561,9562,9564,9567,9569,9571,9573,9575,9578,9580],{"class":644,"line":537},[114,9563,1108],{"class":1107},[114,9565,9566],{"class":745}," badCommand ",[114,9568,1114],{"class":735},[114,9570,2774],{"class":735},[114,9572,6545],{"class":651},[114,9574,2657],{"class":735},[114,9576,9577],{"class":745},"userInput",[114,9579,2933],{"class":735},[114,9581,1098],{"class":735},[114,9583,9584],{"class":644,"line":763},[114,9585,856],{"emptyLinePlaceholder":551},[114,9587,9588],{"class":644,"line":802},[114,9589,9590],{"class":1142},"\u002F\u002F SICHER: Nur alphanumerische Zeichen und Unterstriche erlauben\n",[114,9592,9593,9595,9597,9600,9602,9604,9606,9608,9610,9612],{"class":644,"line":808},[114,9594,1152],{"class":1080},[114,9596,1232],{"class":1107},[114,9598,9599],{"class":1235}," sanitizePlayerName",[114,9601,1239],{"class":735},[114,9603,8324],{"class":1242},[114,9605,1170],{"class":735},[114,9607,1173],{"class":647},[114,9609,1260],{"class":735},[114,9611,1173],{"class":647},[114,9613,1161],{"class":735},[114,9615,9616,9618,9620,9623,9625,9628,9630,9633,9636,9639,9641,9643,9646,9648,9650,9653],{"class":644,"line":814},[114,9617,1308],{"class":1080},[114,9619,257],{"class":1166},[114,9621,9622],{"class":735},"!",[114,9624,2668],{"class":735},[114,9626,9627],{"class":1080},"^",[114,9629,7618],{"class":735},[114,9631,9632],{"class":651},"a-zA-Z0-9_",[114,9634,9635],{"class":735},"]{3,16}",[114,9637,9638],{"class":1080},"$",[114,9640,2668],{"class":735},[114,9642,50],{"class":735},[114,9644,9645],{"class":1235},"test",[114,9647,1239],{"class":1166},[114,9649,8324],{"class":745},[114,9651,9652],{"class":1166},")) ",[114,9654,1330],{"class":735},[114,9656,9657,9659,9661,9663,9665,9667,9670,9672,9674],{"class":644,"line":820},[114,9658,1336],{"class":1080},[114,9660,1339],{"class":735},[114,9662,1342],{"class":1235},[114,9664,1239],{"class":1166},[114,9666,1095],{"class":735},[114,9668,9669],{"class":651},"Ungültiger Spielername (nur 3-16 Buchstaben, Zahlen und Unterstriche erlaubt).",[114,9671,1095],{"class":735},[114,9673,1300],{"class":1166},[114,9675,1098],{"class":735},[114,9677,9678],{"class":644,"line":826},[114,9679,817],{"class":735},[114,9681,9682,9684,9687],{"class":644,"line":832},[114,9683,1560],{"class":1080},[114,9685,9686],{"class":745}," name",[114,9688,1098],{"class":735},[114,9690,9691],{"class":644,"line":891},[114,9692,879],{"class":735},[22,9694,9695],{},"Mit dieser doppelten Absicherung aus Loopback-Isolation und strikter Befehlsvalidierung bleibt dein Minecraft-Server gegen unberechtigte RCON-Zugriffe geschützt.",[944,9697,9698],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":7,"searchDepth":537,"depth":537,"links":9700},[9701,9702,9703,9704,9706],{"id":8699,"depth":537,"text":8700},{"id":8732,"depth":537,"text":8733},{"id":8747,"depth":537,"text":8748},{"id":9471,"depth":537,"text":9705},"4. Server-Konfiguration: Best Practices in server.properties",{"id":9541,"depth":537,"text":9542},"Das Remote Console (RCON) Protokoll von Minecraft ermöglicht die Ausführung beliebiger Server-Befehle über eine TCP-Verbindung. Ein Angreifer, der ein RCON-Passwort knackt, erhält uneingeschränkte Administrator-Rechte auf dem Server (op, stop, whitelist off, Ausführung von NBT-Befehlen). Da das originale Source-RCON-Protokoll aus dem Jahr 2004 stammt und von Haus aus weder Verschlüsselung noch Brute-Force-Schutz bietet, erfordert der Betrieb im Internet strikte Sicherheitsmaßnahmen.",{},"\u002Fdocs\u002Fde\u002Frcon-security-hardening",{"title":9711,"description":9707},{"Minecraft RCON Protokoll Absicherung":9712,"description":9713,"category":1999,"order":537,"author":2000,"readTime":3704,"lastUpdated":2002},"Socket-Hardening & Anti-Brute-Force","Sicherheitsleitfaden für Minecraft RCON-Verbindungen. Schutz vor Klartext-Passwort-Sniffing, Denial-of-Service und Brute-Force-Angriffen.","docs\u002Fde\u002Frcon-security-hardening","aZ5FIh-3fh6dsTukLXcsVZzS85lVIfd6YMT5brV1sTo",{"id":9717,"title":969,"author":12,"body":9718,"category":12,"description":10808,"extension":549,"lastUpdated":12,"meta":10809,"navigation":551,"order":962,"path":10810,"readTime":12,"seo":10811,"stem":10815,"__hash__":10816},"docs\u002Fdocs\u002Fde\u002Fredis-cache-patterns.md",{"type":14,"value":9719,"toc":10801},[9720,9724,9731,9737,9739,9743,9749,9751,9758,9769,9785,10487,10489,10493,10500,10789,10791,10795,10798],[17,9721,9723],{"id":9722},"high-speed-redis-cache-patterns-für-discord-bots-sub-millisekunden-leaderboards","High-Speed Redis Cache Patterns für Discord Bots: Sub-Millisekunden Leaderboards",[22,9725,9726,9727,9730],{},"Wenn ein Discord-Bot auf Tausenden von Servern aktiv ist, führt jede Chat-Nachricht (XP-Vergabe, Level-Aufstiege, Cooldown-Prüfungen) zu Datenbank-Interaktionen. Würde jede Nachricht einen SQL-Befehl auf PostgreSQL absetzen (",[97,9728,9729],{},"SELECT * FROM users WHERE id = ?","), bricht der Datenbank-Verbindungspool bei hoher Aktivität schnell zusammen.",[22,9732,3589,9733,9736],{},[47,9734,9735],{},"Redis"," als In-Memory-Caching-Layer lagern wir transiente Zustände in den RAM aus. Abfragen laufen in unter 1 Millisekunde ab und entlasten die persistente SQL-Datenbank um bis zu 95 %.",[29,9738],{},[32,9740,9742],{"id":9741},"_1-die-caching-topologie-write-through-vs-write-behind","1. Die Caching-Topologie: Write-Through vs. Write-Behind",[635,9744,9747],{"className":9745,"code":9746,"language":1053},[1051],"┌─────────────────────────────────────────────────────────────────┐\n│                     Discord Gateway Events                      │\n└────────────────────────────────┬────────────────────────────────┘\n                                 │\n                                 ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                        KiroCloud Bot Engine                     │\n├────────────────────────────────┬────────────────────────────────┤\n│ 1. Schnelle In-Memory Abfrage  │ 2. Asynchrone Batch-Speicherung│\n│    (Latenz: 0.4 ms)            │    (alle 60 Sekunden)          │\n│    ▼                           │    ▼                           │\n│  ┌───────────────────────┐     │  ┌──────────────────────────┐  │\n│  │     Redis Cache       │     │  │  PostgreSQL Datenbank    │  │\n│  │ (Sorted Sets, TTL)    │     │  │  (Persistente Sicherung) │  │\n│  └───────────────────────┘     │  └──────────────────────────┘  │\n└────────────────────────────────┴────────────────────────────────┘\n",[97,9748,9746],{"__ignoreMap":7},[29,9750],{},[32,9752,9754,9755,1300],{"id":9753},"_2-echtzeit-ranglisten-mit-redis-sorted-sets-zset","2. Echtzeit-Ranglisten mit Redis Sorted Sets (",[97,9756,9757],{},"ZSET",[22,9759,9760,9761,9764,9765,9768],{},"Der naheliegendste Anwendungsfall für Redis in Discord-Bots sind Level- und Coin-Ranglisten (",[97,9762,9763],{},"\u002Fleaderboard","). In SQL erfordert dies ein teures ",[97,9766,9767],{},"ORDER BY xp DESC LIMIT 10",", das bei Tabellen mit Millionen Zeilen erhebliche CPU-Zeit beansprucht.",[22,9770,9771,9772,257,9775,381,9778,381,9781,9784],{},"In Redis nutzen wir ",[47,9773,9774],{},"Sorted Sets",[97,9776,9777],{},"ZADD",[97,9779,9780],{},"ZREVRANGE",[97,9782,9783],{},"ZREVRANK","), die intern als Skip-Lists organisiert sind und Rangabfragen in $O(\\log N)$ Komplexität lösen:",[635,9786,9788],{"className":1071,"code":9787,"language":1073,"meta":7,"style":7},"import Redis from 'ioredis';\n\nconst redis = new Redis(process.env.REDIS_URL || 'redis:\u002F\u002Flocalhost:6379');\n\n\u002F**\n * Erhöht die Erfahrungspunkte eines Nutzers auf einem Server\n *\u002F\nexport async function addGuildUserXp(guildId: string, userId: string, xpDelta: number): Promise\u003Cnumber> {\n  const leaderboardKey = `guild:${guildId}:xp_leaderboard`;\n\n  \u002F\u002F ZINCRBY erhöht den Score atomar und liefert den neuen Wert zurück\n  const newXp = await redis.zincrby(leaderboardKey, xpDelta, userId);\n  return parseFloat(newXp);\n}\n\n\u002F**\n * Ermittelt die Top 10 Nutzer eines Servers in Sub-Millisekunden\n *\u002F\nexport async function getTopUsers(guildId: string, limit = 10): Promise\u003CArray\u003C{ userId: string; score: number }>> {\n  const leaderboardKey = `guild:${guildId}:xp_leaderboard`;\n\n  \u002F\u002F ZREVRANGE mit WITHSCORES liefert die ranghöchsten Einträge\n  const rawResults = await redis.zrevrange(leaderboardKey, 0, limit - 1, 'WITHSCORES');\n\n  const formatted: Array\u003C{ userId: string; score: number }> = [];\n  for (let i = 0; i \u003C rawResults.length; i += 2) {\n    formatted.push({\n      userId: rawResults[i],\n      score: parseFloat(rawResults[i + 1]),\n    });\n  }\n\n  return formatted;\n}\n\n\u002F**\n * Ermittelt den genauen Platz (Rank) eines bestimmten Nutzers\n *\u002F\nexport async function getUserRank(guildId: string, userId: string): Promise\u003Cnumber | null> {\n  const leaderboardKey = `guild:${guildId}:xp_leaderboard`;\n  \u002F\u002F ZREVRANK liefert den 0-basierten Index absteigend sortiert\n  const rank = await redis.zrevrank(leaderboardKey, userId);\n  return rank !== null ? rank + 1 : null;\n}\n",[97,9789,9790,9806,9810,9848,9852,9856,9861,9865,9916,9943,9947,9952,9987,10003,10007,10011,10015,10020,10024,10085,10109,10113,10118,10165,10169,10207,10249,10263,10282,10309,10317,10321,10325,10333,10337,10341,10345,10350,10354,10399,10423,10428,10458,10483],{"__ignoreMap":7},[114,9791,9792,9794,9796,9798,9800,9802,9804],{"class":644,"line":552},[114,9793,1081],{"class":1080},[114,9795,6114],{"class":745},[114,9797,1087],{"class":1080},[114,9799,1090],{"class":735},[114,9801,6121],{"class":651},[114,9803,1095],{"class":735},[114,9805,1098],{"class":735},[114,9807,9808],{"class":644,"line":537},[114,9809,856],{"emptyLinePlaceholder":551},[114,9811,9812,9814,9816,9818,9820,9822,9825,9827,9829,9831,9834,9837,9839,9842,9844,9846],{"class":644,"line":763},[114,9813,1108],{"class":1107},[114,9815,6136],{"class":745},[114,9817,1114],{"class":735},[114,9819,1339],{"class":735},[114,9821,6143],{"class":1235},[114,9823,9824],{"class":745},"(process",[114,9826,50],{"class":735},[114,9828,3861],{"class":745},[114,9830,50],{"class":735},[114,9832,9833],{"class":745},"REDIS_URL ",[114,9835,9836],{"class":735},"||",[114,9838,1090],{"class":735},[114,9840,9841],{"class":651},"redis:\u002F\u002Flocalhost:6379",[114,9843,1095],{"class":735},[114,9845,1300],{"class":745},[114,9847,1098],{"class":735},[114,9849,9850],{"class":644,"line":802},[114,9851,856],{"emptyLinePlaceholder":551},[114,9853,9854],{"class":644,"line":808},[114,9855,1212],{"class":1142},[114,9857,9858],{"class":644,"line":814},[114,9859,9860],{"class":1142}," * Erhöht die Erfahrungspunkte eines Nutzers auf einem Server\n",[114,9862,9863],{"class":644,"line":820},[114,9864,1224],{"class":1142},[114,9866,9867,9869,9871,9873,9876,9878,9881,9883,9885,9887,9890,9892,9894,9896,9899,9901,9903,9905,9907,9909,9912,9914],{"class":644,"line":826},[114,9868,1152],{"class":1080},[114,9870,4354],{"class":1107},[114,9872,1232],{"class":1107},[114,9874,9875],{"class":1235}," addGuildUserXp",[114,9877,1239],{"class":735},[114,9879,9880],{"class":1242},"guildId",[114,9882,1170],{"class":735},[114,9884,1173],{"class":647},[114,9886,1250],{"class":735},[114,9888,9889],{"class":1242}," userId",[114,9891,1170],{"class":735},[114,9893,1173],{"class":647},[114,9895,1250],{"class":735},[114,9897,9898],{"class":1242}," xpDelta",[114,9900,1170],{"class":735},[114,9902,3506],{"class":647},[114,9904,1260],{"class":735},[114,9906,4801],{"class":647},[114,9908,3499],{"class":735},[114,9910,9911],{"class":647},"number",[114,9913,3509],{"class":735},[114,9915,1161],{"class":735},[114,9917,9918,9920,9923,9925,9927,9930,9932,9934,9936,9939,9941],{"class":644,"line":832},[114,9919,1270],{"class":1107},[114,9921,9922],{"class":745}," leaderboardKey",[114,9924,1276],{"class":735},[114,9926,2774],{"class":735},[114,9928,9929],{"class":651},"guild:",[114,9931,2657],{"class":735},[114,9933,9880],{"class":745},[114,9935,2693],{"class":735},[114,9937,9938],{"class":651},":xp_leaderboard",[114,9940,2651],{"class":735},[114,9942,1098],{"class":735},[114,9944,9945],{"class":644,"line":891},[114,9946,856],{"emptyLinePlaceholder":551},[114,9948,9949],{"class":644,"line":1204},[114,9950,9951],{"class":1142},"  \u002F\u002F ZINCRBY erhöht den Score atomar und liefert den neuen Wert zurück\n",[114,9953,9954,9956,9959,9961,9963,9965,9967,9970,9972,9975,9977,9979,9981,9983,9985],{"class":644,"line":1209},[114,9955,1270],{"class":1107},[114,9957,9958],{"class":745}," newXp",[114,9960,1276],{"class":735},[114,9962,4383],{"class":1080},[114,9964,6263],{"class":745},[114,9966,50],{"class":735},[114,9968,9969],{"class":1235},"zincrby",[114,9971,1239],{"class":1166},[114,9973,9974],{"class":745},"leaderboardKey",[114,9976,1250],{"class":735},[114,9978,9898],{"class":745},[114,9980,1250],{"class":735},[114,9982,9889],{"class":745},[114,9984,1300],{"class":1166},[114,9986,1098],{"class":735},[114,9988,9989,9991,9994,9996,9999,10001],{"class":644,"line":1215},[114,9990,1560],{"class":1080},[114,9992,9993],{"class":1235}," parseFloat",[114,9995,1239],{"class":1166},[114,9997,9998],{"class":745},"newXp",[114,10000,1300],{"class":1166},[114,10002,1098],{"class":735},[114,10004,10005],{"class":644,"line":1221},[114,10006,879],{"class":735},[114,10008,10009],{"class":644,"line":1227},[114,10010,856],{"emptyLinePlaceholder":551},[114,10012,10013],{"class":644,"line":1267},[114,10014,1212],{"class":1142},[114,10016,10017],{"class":644,"line":1305},[114,10018,10019],{"class":1142}," * Ermittelt die Top 10 Nutzer eines Servers in Sub-Millisekunden\n",[114,10021,10022],{"class":644,"line":1333},[114,10023,1224],{"class":1142},[114,10025,10026,10028,10030,10032,10035,10037,10039,10041,10043,10045,10048,10050,10053,10055,10057,10059,10062,10065,10067,10069,10071,10073,10076,10078,10080,10083],{"class":644,"line":1358},[114,10027,1152],{"class":1080},[114,10029,4354],{"class":1107},[114,10031,1232],{"class":1107},[114,10033,10034],{"class":1235}," getTopUsers",[114,10036,1239],{"class":735},[114,10038,9880],{"class":1242},[114,10040,1170],{"class":735},[114,10042,1173],{"class":647},[114,10044,1250],{"class":735},[114,10046,10047],{"class":1242}," limit",[114,10049,1276],{"class":735},[114,10051,10052],{"class":1135}," 10",[114,10054,1260],{"class":735},[114,10056,4801],{"class":647},[114,10058,3499],{"class":735},[114,10060,10061],{"class":647},"Array",[114,10063,10064],{"class":735},"\u003C{",[114,10066,9889],{"class":1166},[114,10068,1170],{"class":735},[114,10070,1173],{"class":647},[114,10072,1139],{"class":735},[114,10074,10075],{"class":1166}," score",[114,10077,1170],{"class":735},[114,10079,3506],{"class":647},[114,10081,10082],{"class":735}," }>>",[114,10084,1161],{"class":735},[114,10086,10087,10089,10091,10093,10095,10097,10099,10101,10103,10105,10107],{"class":644,"line":1363},[114,10088,1270],{"class":1107},[114,10090,9922],{"class":745},[114,10092,1276],{"class":735},[114,10094,2774],{"class":735},[114,10096,9929],{"class":651},[114,10098,2657],{"class":735},[114,10100,9880],{"class":745},[114,10102,2693],{"class":735},[114,10104,9938],{"class":651},[114,10106,2651],{"class":735},[114,10108,1098],{"class":735},[114,10110,10111],{"class":644,"line":1368},[114,10112,856],{"emptyLinePlaceholder":551},[114,10114,10115],{"class":644,"line":1374},[114,10116,10117],{"class":1142},"  \u002F\u002F ZREVRANGE mit WITHSCORES liefert die ranghöchsten Einträge\n",[114,10119,10120,10122,10125,10127,10129,10131,10133,10136,10138,10140,10142,10144,10146,10148,10150,10152,10154,10156,10159,10161,10163],{"class":644,"line":1401},[114,10121,1270],{"class":1107},[114,10123,10124],{"class":745}," rawResults",[114,10126,1276],{"class":735},[114,10128,4383],{"class":1080},[114,10130,6263],{"class":745},[114,10132,50],{"class":735},[114,10134,10135],{"class":1235},"zrevrange",[114,10137,1239],{"class":1166},[114,10139,9974],{"class":745},[114,10141,1250],{"class":735},[114,10143,3186],{"class":1135},[114,10145,1250],{"class":735},[114,10147,10047],{"class":745},[114,10149,9036],{"class":735},[114,10151,4956],{"class":1135},[114,10153,1250],{"class":735},[114,10155,1090],{"class":735},[114,10157,10158],{"class":651},"WITHSCORES",[114,10160,1095],{"class":735},[114,10162,1300],{"class":1166},[114,10164,1098],{"class":735},[114,10166,10167],{"class":644,"line":1435},[114,10168,856],{"emptyLinePlaceholder":551},[114,10170,10171,10173,10176,10178,10181,10183,10185,10187,10189,10191,10193,10195,10197,10200,10202,10205],{"class":644,"line":1440},[114,10172,1270],{"class":1107},[114,10174,10175],{"class":745}," formatted",[114,10177,1170],{"class":735},[114,10179,10180],{"class":647}," Array",[114,10182,10064],{"class":735},[114,10184,9889],{"class":1166},[114,10186,1170],{"class":735},[114,10188,1173],{"class":647},[114,10190,1139],{"class":735},[114,10192,10075],{"class":1166},[114,10194,1170],{"class":735},[114,10196,3506],{"class":647},[114,10198,10199],{"class":735}," }>",[114,10201,1276],{"class":735},[114,10203,10204],{"class":1166}," []",[114,10206,1098],{"class":735},[114,10208,10209,10212,10214,10217,10220,10222,10224,10226,10228,10230,10232,10234,10236,10238,10240,10242,10245,10247],{"class":644,"line":1483},[114,10210,10211],{"class":1080},"  for",[114,10213,257],{"class":1166},[114,10215,10216],{"class":1107},"let",[114,10218,10219],{"class":745}," i",[114,10221,1276],{"class":735},[114,10223,3186],{"class":1135},[114,10225,1139],{"class":735},[114,10227,10219],{"class":745},[114,10229,4854],{"class":735},[114,10231,10124],{"class":745},[114,10233,50],{"class":735},[114,10235,1318],{"class":745},[114,10237,1139],{"class":735},[114,10239,10219],{"class":745},[114,10241,1488],{"class":735},[114,10243,10244],{"class":1135}," 2",[114,10246,1327],{"class":1166},[114,10248,1330],{"class":735},[114,10250,10251,10254,10256,10259,10261],{"class":644,"line":1510},[114,10252,10253],{"class":745},"    formatted",[114,10255,50],{"class":735},[114,10257,10258],{"class":1235},"push",[114,10260,1239],{"class":1166},[114,10262,1330],{"class":735},[114,10264,10265,10268,10270,10272,10274,10277,10280],{"class":644,"line":1515},[114,10266,10267],{"class":1166},"      userId",[114,10269,1170],{"class":735},[114,10271,10124],{"class":745},[114,10273,7618],{"class":1166},[114,10275,10276],{"class":745},"i",[114,10278,10279],{"class":1166},"]",[114,10281,1571],{"class":735},[114,10283,10284,10287,10289,10291,10293,10296,10298,10300,10302,10304,10307],{"class":644,"line":1552},[114,10285,10286],{"class":1166},"      score",[114,10288,1170],{"class":735},[114,10290,9993],{"class":1235},[114,10292,1239],{"class":1166},[114,10294,10295],{"class":745},"rawResults",[114,10297,7618],{"class":1166},[114,10299,10276],{"class":745},[114,10301,4479],{"class":735},[114,10303,4956],{"class":1135},[114,10305,10306],{"class":1166},"])",[114,10308,1571],{"class":735},[114,10310,10311,10313,10315],{"class":644,"line":1557},[114,10312,4886],{"class":735},[114,10314,1300],{"class":1166},[114,10316,1098],{"class":735},[114,10318,10319],{"class":644,"line":1565},[114,10320,817],{"class":735},[114,10322,10323],{"class":644,"line":1574},[114,10324,856],{"emptyLinePlaceholder":551},[114,10326,10327,10329,10331],{"class":644,"line":1600},[114,10328,1560],{"class":1080},[114,10330,10175],{"class":745},[114,10332,1098],{"class":735},[114,10334,10335],{"class":644,"line":1608},[114,10336,879],{"class":735},[114,10338,10339],{"class":644,"line":1614},[114,10340,856],{"emptyLinePlaceholder":551},[114,10342,10343],{"class":644,"line":1619},[114,10344,1212],{"class":1142},[114,10346,10347],{"class":644,"line":1624},[114,10348,10349],{"class":1142}," * Ermittelt den genauen Platz (Rank) eines bestimmten Nutzers\n",[114,10351,10352],{"class":644,"line":1629},[114,10353,1224],{"class":1142},[114,10355,10356,10358,10360,10362,10365,10367,10369,10371,10373,10375,10377,10379,10381,10383,10385,10387,10389,10392,10395,10397],{"class":644,"line":1635},[114,10357,1152],{"class":1080},[114,10359,4354],{"class":1107},[114,10361,1232],{"class":1107},[114,10363,10364],{"class":1235}," getUserRank",[114,10366,1239],{"class":735},[114,10368,9880],{"class":1242},[114,10370,1170],{"class":735},[114,10372,1173],{"class":647},[114,10374,1250],{"class":735},[114,10376,9889],{"class":1242},[114,10378,1170],{"class":735},[114,10380,1173],{"class":647},[114,10382,1260],{"class":735},[114,10384,4801],{"class":647},[114,10386,3499],{"class":735},[114,10388,9911],{"class":647},[114,10390,10391],{"class":735}," |",[114,10393,10394],{"class":647}," null",[114,10396,3509],{"class":735},[114,10398,1161],{"class":735},[114,10400,10401,10403,10405,10407,10409,10411,10413,10415,10417,10419,10421],{"class":644,"line":1640},[114,10402,1270],{"class":1107},[114,10404,9922],{"class":745},[114,10406,1276],{"class":735},[114,10408,2774],{"class":735},[114,10410,9929],{"class":651},[114,10412,2657],{"class":735},[114,10414,9880],{"class":745},[114,10416,2693],{"class":735},[114,10418,9938],{"class":651},[114,10420,2651],{"class":735},[114,10422,1098],{"class":735},[114,10424,10425],{"class":644,"line":1673},[114,10426,10427],{"class":1142},"  \u002F\u002F ZREVRANK liefert den 0-basierten Index absteigend sortiert\n",[114,10429,10430,10432,10435,10437,10439,10441,10443,10446,10448,10450,10452,10454,10456],{"class":644,"line":1704},[114,10431,1270],{"class":1107},[114,10433,10434],{"class":745}," rank",[114,10436,1276],{"class":735},[114,10438,4383],{"class":1080},[114,10440,6263],{"class":745},[114,10442,50],{"class":735},[114,10444,10445],{"class":1235},"zrevrank",[114,10447,1239],{"class":1166},[114,10449,9974],{"class":745},[114,10451,1250],{"class":735},[114,10453,9889],{"class":745},[114,10455,1300],{"class":1166},[114,10457,1098],{"class":735},[114,10459,10460,10462,10464,10466,10468,10471,10473,10475,10477,10480],{"class":644,"line":1740},[114,10461,1560],{"class":1080},[114,10463,10434],{"class":745},[114,10465,1321],{"class":735},[114,10467,10394],{"class":735},[114,10469,10470],{"class":735}," ?",[114,10472,10434],{"class":745},[114,10474,4479],{"class":735},[114,10476,4956],{"class":1135},[114,10478,10479],{"class":735}," :",[114,10481,10482],{"class":735}," null;\n",[114,10484,10485],{"class":644,"line":1775},[114,10486,879],{"class":735},[29,10488],{},[32,10490,10492],{"id":10491},"_3-cooldown-verwaltung-mit-automatischer-ttl-verfallszeit","3. Cooldown-Verwaltung mit automatischer TTL-Verfallszeit",[22,10494,10495,10496,10499],{},"Befehls-Cooldowns (z. B. 5 Sekunden Pause zwischen ",[97,10497,10498],{},"\u002Fdaily",") erfordern keine persistente Speicherung. Mit Redis-TTL verfällt der Schlüssel automatisch:",[635,10501,10503],{"className":1071,"code":10502,"language":1073,"meta":7,"style":7},"export async function checkRateLimit(userId: string, action: string, windowSeconds: number): Promise\u003C{ allowed: boolean; remainingSec: number }> {\n  const key = `ratelimit:${userId}:${action}`;\n\n  \u002F\u002F SET mit NX (nur setzen wenn nicht existiert) und EX (Ablaufzeit)\n  const acquired = await redis.set(key, '1', 'EX', windowSeconds, 'NX');\n\n  if (acquired === 'OK') {\n    return { allowed: true, remainingSec: 0 };\n  }\n\n  const ttl = await redis.ttl(key);\n  return { allowed: false, remainingSec: Math.max(0, ttl) };\n}\n",[97,10504,10505,10569,10599,10603,10608,10663,10667,10689,10711,10715,10719,10745,10785],{"__ignoreMap":7},[114,10506,10507,10509,10511,10513,10516,10518,10521,10523,10525,10527,10530,10532,10534,10536,10539,10541,10543,10545,10547,10549,10552,10554,10557,10559,10561,10563,10565,10567],{"class":644,"line":552},[114,10508,1152],{"class":1080},[114,10510,4354],{"class":1107},[114,10512,1232],{"class":1107},[114,10514,10515],{"class":1235}," checkRateLimit",[114,10517,1239],{"class":735},[114,10519,10520],{"class":1242},"userId",[114,10522,1170],{"class":735},[114,10524,1173],{"class":647},[114,10526,1250],{"class":735},[114,10528,10529],{"class":1242}," action",[114,10531,1170],{"class":735},[114,10533,1173],{"class":647},[114,10535,1250],{"class":735},[114,10537,10538],{"class":1242}," windowSeconds",[114,10540,1170],{"class":735},[114,10542,3506],{"class":647},[114,10544,1260],{"class":735},[114,10546,4801],{"class":647},[114,10548,10064],{"class":735},[114,10550,10551],{"class":1166}," allowed",[114,10553,1170],{"class":735},[114,10555,10556],{"class":647}," boolean",[114,10558,1139],{"class":735},[114,10560,9015],{"class":1166},[114,10562,1170],{"class":735},[114,10564,3506],{"class":647},[114,10566,10199],{"class":735},[114,10568,1161],{"class":735},[114,10570,10571,10573,10575,10577,10579,10582,10584,10586,10588,10590,10592,10595,10597],{"class":644,"line":537},[114,10572,1270],{"class":1107},[114,10574,1273],{"class":745},[114,10576,1276],{"class":735},[114,10578,2774],{"class":735},[114,10580,10581],{"class":651},"ratelimit:",[114,10583,2657],{"class":735},[114,10585,10520],{"class":745},[114,10587,2693],{"class":735},[114,10589,1170],{"class":651},[114,10591,2657],{"class":735},[114,10593,10594],{"class":745},"action",[114,10596,2933],{"class":735},[114,10598,1098],{"class":735},[114,10600,10601],{"class":644,"line":763},[114,10602,856],{"emptyLinePlaceholder":551},[114,10604,10605],{"class":644,"line":802},[114,10606,10607],{"class":1142},"  \u002F\u002F SET mit NX (nur setzen wenn nicht existiert) und EX (Ablaufzeit)\n",[114,10609,10610,10612,10615,10617,10619,10621,10623,10625,10627,10629,10631,10633,10635,10637,10639,10641,10644,10646,10648,10650,10652,10654,10657,10659,10661],{"class":644,"line":808},[114,10611,1270],{"class":1107},[114,10613,10614],{"class":745}," acquired",[114,10616,1276],{"class":735},[114,10618,4383],{"class":1080},[114,10620,6263],{"class":745},[114,10622,50],{"class":735},[114,10624,3558],{"class":1235},[114,10626,1239],{"class":1166},[114,10628,1313],{"class":745},[114,10630,1250],{"class":735},[114,10632,1090],{"class":735},[114,10634,9227],{"class":651},[114,10636,1095],{"class":735},[114,10638,1250],{"class":735},[114,10640,1090],{"class":735},[114,10642,10643],{"class":651},"EX",[114,10645,1095],{"class":735},[114,10647,1250],{"class":735},[114,10649,10538],{"class":745},[114,10651,1250],{"class":735},[114,10653,1090],{"class":735},[114,10655,10656],{"class":651},"NX",[114,10658,1095],{"class":735},[114,10660,1300],{"class":1166},[114,10662,1098],{"class":735},[114,10664,10665],{"class":644,"line":814},[114,10666,856],{"emptyLinePlaceholder":551},[114,10668,10669,10671,10673,10676,10678,10680,10683,10685,10687],{"class":644,"line":820},[114,10670,1308],{"class":1080},[114,10672,257],{"class":1166},[114,10674,10675],{"class":745},"acquired",[114,10677,4919],{"class":735},[114,10679,1090],{"class":735},[114,10681,10682],{"class":651},"OK",[114,10684,1095],{"class":735},[114,10686,1327],{"class":1166},[114,10688,1330],{"class":735},[114,10690,10691,10693,10695,10697,10699,10701,10703,10705,10707,10709],{"class":644,"line":826},[114,10692,4407],{"class":1080},[114,10694,3035],{"class":735},[114,10696,10551],{"class":1166},[114,10698,1170],{"class":735},[114,10700,3898],{"class":3897},[114,10702,1250],{"class":735},[114,10704,9015],{"class":1166},[114,10706,1170],{"class":735},[114,10708,3186],{"class":1135},[114,10710,4719],{"class":735},[114,10712,10713],{"class":644,"line":832},[114,10714,817],{"class":735},[114,10716,10717],{"class":644,"line":891},[114,10718,856],{"emptyLinePlaceholder":551},[114,10720,10721,10723,10726,10728,10730,10732,10734,10737,10739,10741,10743],{"class":644,"line":1204},[114,10722,1270],{"class":1107},[114,10724,10725],{"class":745}," ttl",[114,10727,1276],{"class":735},[114,10729,4383],{"class":1080},[114,10731,6263],{"class":745},[114,10733,50],{"class":735},[114,10735,10736],{"class":1235},"ttl",[114,10738,1239],{"class":1166},[114,10740,1313],{"class":745},[114,10742,1300],{"class":1166},[114,10744,1098],{"class":735},[114,10746,10747,10749,10751,10753,10755,10758,10760,10762,10764,10766,10768,10771,10773,10776,10778,10780,10782],{"class":644,"line":1209},[114,10748,1560],{"class":1080},[114,10750,3035],{"class":735},[114,10752,10551],{"class":1166},[114,10754,1170],{"class":735},[114,10756,10757],{"class":3897}," false",[114,10759,1250],{"class":735},[114,10761,9015],{"class":1166},[114,10763,1170],{"class":735},[114,10765,4640],{"class":745},[114,10767,50],{"class":735},[114,10769,10770],{"class":1235},"max",[114,10772,1239],{"class":1166},[114,10774,10775],{"class":1135},"0",[114,10777,1250],{"class":735},[114,10779,10725],{"class":745},[114,10781,1327],{"class":1166},[114,10783,10784],{"class":735},"};\n",[114,10786,10787],{"class":644,"line":1215},[114,10788,879],{"class":735},[29,10790],{},[32,10792,10794],{"id":10793},"_4-cache-invalidierung-postgresql-synchronisation","4. Cache-Invalidierung & PostgreSQL-Synchronisation",[22,10796,10797],{},"Um Datenverlust bei Server-Neustarts zu verhindern, synchronisieren wir geänderte Redis-Scores periodisch in die relationale PostgreSQL-Datenbank (Write-Behind-Pattern). Dies geschieht im Hintergrund alle 60 Sekunden ohne Blockierung des Discord-Event-Loops.",[944,10799,10800],{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":7,"searchDepth":537,"depth":537,"links":10802},[10803,10804,10806,10807],{"id":9741,"depth":537,"text":9742},{"id":9753,"depth":537,"text":10805},"2. Echtzeit-Ranglisten mit Redis Sorted Sets (ZSET)",{"id":10491,"depth":537,"text":10492},{"id":10793,"depth":537,"text":10794},"Wenn ein Discord-Bot auf Tausenden von Servern aktiv ist, führt jede Chat-Nachricht (XP-Vergabe, Level-Aufstiege, Cooldown-Prüfungen) zu Datenbank-Interaktionen. Würde jede Nachricht einen SQL-Befehl auf PostgreSQL absetzen (SELECT * FROM users WHERE id = ?), bricht der Datenbank-Verbindungspool bei hoher Aktivität schnell zusammen.",{},"\u002Fdocs\u002Fde\u002Fredis-cache-patterns",{"title":10812,"description":10808},{"High-Speed Redis Cache Patterns für Discord Bots":10813,"description":10814,"category":6034,"order":537,"author":2000,"readTime":8510,"lastUpdated":2002},"Sub-Millisekunden Leaderboards","Architekturleitfaden für Redis Caching in Discord-Bots. Sorted Sets für globale Leaderboards, Key-TTL Strategien und Cache-Invalidierung.","docs\u002Fde\u002Fredis-cache-patterns","wc1CRxXggZbMNTRkgWQ04pFPemd-SI5JovvmAbbfFbI",{"id":10818,"title":10819,"author":12,"body":10820,"category":958,"description":13637,"extension":549,"lastUpdated":12,"meta":13638,"navigation":551,"order":962,"path":13640,"readTime":12,"seo":13641,"stem":13642,"__hash__":13643},"docs\u002Fdocs\u002Fde\u002Frest-endpoints.md","KiroCloud REST API Referenz",{"type":14,"value":10821,"toc":13621},[10822,10826,10829,10836,10838,10842,10848,10852,10874,10881,10883,10887,10890,10894,10897,12526,12528,12532,12538,12749,12751,12755,12758,12957,12959,12963,12967,12975,12978,12993,13147,13153,13156,13162,13164,13168,13174,13177,13191,13197,13200,13208,13215,13218,13234,13240,13247,13255,13261,13264,13272,13278,13281,13294,13397,13399,13403,13409,13412,13420,13425,13428,13440,13509,13511,13515,13518,13618],[17,10823,10825],{"id":10824},"kirocloud-rest-api-sdk-dokumentation","KiroCloud REST API & SDK Dokumentation",[22,10827,10828],{},"Herzlich willkommen zur offiziellen KiroCloud REST API-Referenz für Entwickler und Bot-Betreiber.\nDiese Dokumentation bietet alle notwendigen Spezifikationen, Endpunkte und SDK-Beispiele, um KiroCloud in eigene Anwendungen, Überwachungs-Tools oder CI\u002FCD-Pipelines zu integrieren.",[109,10830,10831],{},[22,10832,10833,10835],{},[114,10834,181],{},"\nAlle Anfragen an authentifizierte Endpunkte erfordern einen gültigen API-Schlüssel, der im HTTP-Header mitgesendet werden muss. Teile deinen API-Schlüssel niemals öffentlich (z. B. in GitHub-Repositories oder Client-seitigem Frontend-Code).",[29,10837],{},[32,10839,10841],{"id":10840},"_1-authentifizierung","1. Authentifizierung",[22,10843,10844,10845,10847],{},"Um Anfragen an die API zu senden, übergibst du deinen API-Schlüssel im ",[97,10846,632],{},"-Header als Bearer Token.",[714,10849,10851],{"id":10850},"header-format","Header-Format",[635,10853,10857],{"className":10854,"code":10855,"language":10856,"meta":7,"style":7},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","Authorization: Bearer kiro_sec_DEIN_API_SCHLUESSEL\nContent-Type: application\u002Fjson\nAccept: application\u002Fjson\n","http",[97,10858,10859,10864,10869],{"__ignoreMap":7},[114,10860,10861],{"class":644,"line":552},[114,10862,10863],{},"Authorization: Bearer kiro_sec_DEIN_API_SCHLUESSEL\n",[114,10865,10866],{"class":644,"line":537},[114,10867,10868],{},"Content-Type: application\u002Fjson\n",[114,10870,10871],{"class":644,"line":763},[114,10872,10873],{},"Accept: application\u002Fjson\n",[22,10875,10876,10877,10880],{},"API-Schlüssel können direkt im KiroCloud Dashboard unter den ",[47,10878,10879],{},"Entwickler-Einstellungen"," erstellt und mit spezifischen Berechtigungen (Scopes) versehen werden.",[29,10882],{},[32,10884,10886],{"id":10885},"_2-fertige-sdk-wrapper-für-deine-projekte","2. Fertige SDK-Wrapper für deine Projekte",[22,10888,10889],{},"Damit du nicht jeden HTTP-Request manuell implementieren musst, findest du hier produktionsreife Client-Klassen für Node.js \u002F TypeScript, Python und Bash.",[714,10891,10893],{"id":10892},"_21-nodejs-typescript-native-fetch-api","2.1 Node.js \u002F TypeScript (Native Fetch API)",[22,10895,10896],{},"Optimiert für moderne Node.js-Umgebungen (ab v18) und Edge-Runtimes:",[635,10898,10900],{"className":1071,"code":10899,"language":1073,"meta":7,"style":7},"\u002F\u002F kiroClient.ts\nexport interface BotStatusResponse {\n  success: boolean;\n  data: {\n    id: string;\n    name: string;\n    status: 'online' | 'offline' | 'starting' | 'error';\n    runtimeExpiresAt: string;\n    uptimeSeconds: number;\n  };\n}\n\nexport class KiroClient {\n  private baseUrl: string;\n  private apiKey: string;\n\n  constructor(apiKey: string, baseUrl = 'https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1') {\n    this.apiKey = apiKey;\n    this.baseUrl = baseUrl;\n  }\n\n  private async request\u003CT>(method: string, endpoint: string, body?: unknown): Promise\u003CT> {\n    const headers: Record\u003Cstring, string> = {\n      'Authorization': `Bearer ${this.apiKey}`,\n      'Content-Type': 'application\u002Fjson',\n      'Accept': 'application\u002Fjson',\n    };\n\n    const response = await fetch(`${this.baseUrl}${endpoint}`, {\n      method,\n      headers,\n      body: body ? JSON.stringify(body) : undefined,\n    });\n\n    if (!response.ok) {\n      const errorData = await response.json().catch(() => ({}));\n      throw new Error(`KiroCloud API Error [${response.status}]: ${errorData.message || response.statusText}`);\n    }\n\n    return response.json() as Promise\u003CT>;\n  }\n\n  \u002F\u002F --- Public Status & Platform Health ---\n\n  async getPlatformStatus() {\n    return this.request\u003C{ success: boolean; data: Record\u003Cstring, unknown> }>('GET', '\u002Fpublic\u002Fstatus');\n  }\n\n  async getPlatformStats() {\n    return this.request\u003C{ success: boolean; data: { activeBots: number; activeServers: number; uptime: number } }>('GET', '\u002Fpublic\u002Fstats');\n  }\n\n  \u002F\u002F --- Bot Management (Scope: bots:read, bots:write) ---\n\n  async listBots() {\n    return this.request\u003C{ success: boolean; data: Array\u003C{ id: string; name: string; status: string }> }>('GET', '\u002Fbots');\n  }\n\n  async getBot(botId: string) {\n    return this.request\u003CBotStatusResponse>('GET', `\u002Fbots\u002F${botId}`);\n  }\n\n  async startBot(botId: string) {\n    return this.request\u003C{ success: boolean; message: string }>('POST', `\u002Fbots\u002F${botId}\u002Fstart`);\n  }\n\n  async stopBot(botId: string) {\n    return this.request\u003C{ success: boolean; message: string }>('POST', `\u002Fbots\u002F${botId}\u002Fstop`);\n  }\n\n  async restartBot(botId: string) {\n    return this.request\u003C{ success: boolean; message: string }>('POST', `\u002Fbots\u002F${botId}\u002Frestart`);\n  }\n\n  async sendEmbed(botId: string, payload: { channelId: string; embed: Record\u003Cstring, unknown> }) {\n    return this.request\u003C{ success: boolean; messageId: string }>('POST', `\u002Fbots\u002F${botId}\u002Fsend-embed`, payload);\n  }\n\n  \u002F\u002F --- Support Tickets (Scope: tickets:read, tickets:write) ---\n\n  async listTickets() {\n    return this.request\u003C{ success: boolean; data: Array\u003C{ id: string; subject: string; status: string }> }>('GET', '\u002Ftickets');\n  }\n\n  async createTicket(payload: { subject: string; message: string; priority?: 'low' | 'normal' | 'high' }) {\n    return this.request\u003C{ success: boolean; ticketId: string }>('POST', '\u002Ftickets', payload);\n  }\n}\n",[97,10901,10902,10907,10918,10929,10938,10949,10960,11002,11013,11024,11028,11032,11036,11048,11062,11075,11079,11110,11123,11136,11140,11144,11198,11224,11251,11271,11290,11294,11298,11333,11340,11347,11376,11384,11388,11408,11446,11500,11504,11508,11532,11536,11540,11545,11549,11561,11622,11626,11630,11641,11715,11719,11723,11729,11734,11746,11822,11827,11832,11852,11893,11898,11903,11923,11980,11985,11990,12010,12066,12071,12076,12096,12152,12157,12162,12218,12279,12284,12289,12295,12300,12312,12387,12392,12397,12464,12516,12521],{"__ignoreMap":7},[114,10903,10904],{"class":644,"line":552},[114,10905,10906],{"class":1142},"\u002F\u002F kiroClient.ts\n",[114,10908,10909,10911,10913,10916],{"class":644,"line":537},[114,10910,1152],{"class":1080},[114,10912,1155],{"class":1107},[114,10914,10915],{"class":647}," BotStatusResponse",[114,10917,1161],{"class":735},[114,10919,10920,10923,10925,10927],{"class":644,"line":763},[114,10921,10922],{"class":1166},"  success",[114,10924,1170],{"class":735},[114,10926,10556],{"class":647},[114,10928,1098],{"class":735},[114,10930,10931,10934,10936],{"class":644,"line":802},[114,10932,10933],{"class":1166},"  data",[114,10935,1170],{"class":735},[114,10937,1161],{"class":735},[114,10939,10940,10943,10945,10947],{"class":644,"line":808},[114,10941,10942],{"class":1166},"    id",[114,10944,1170],{"class":735},[114,10946,1173],{"class":647},[114,10948,1098],{"class":735},[114,10950,10951,10954,10956,10958],{"class":644,"line":814},[114,10952,10953],{"class":1166},"    name",[114,10955,1170],{"class":735},[114,10957,1173],{"class":647},[114,10959,1098],{"class":735},[114,10961,10962,10965,10967,10969,10972,10974,10976,10978,10981,10983,10985,10987,10990,10992,10994,10996,10998,11000],{"class":644,"line":820},[114,10963,10964],{"class":1166},"    status",[114,10966,1170],{"class":735},[114,10968,1090],{"class":735},[114,10970,10971],{"class":651},"online",[114,10973,1095],{"class":735},[114,10975,10391],{"class":735},[114,10977,1090],{"class":735},[114,10979,10980],{"class":651},"offline",[114,10982,1095],{"class":735},[114,10984,10391],{"class":735},[114,10986,1090],{"class":735},[114,10988,10989],{"class":651},"starting",[114,10991,1095],{"class":735},[114,10993,10391],{"class":735},[114,10995,1090],{"class":735},[114,10997,4281],{"class":651},[114,10999,1095],{"class":735},[114,11001,1098],{"class":735},[114,11003,11004,11007,11009,11011],{"class":644,"line":826},[114,11005,11006],{"class":1166},"    runtimeExpiresAt",[114,11008,1170],{"class":735},[114,11010,1173],{"class":647},[114,11012,1098],{"class":735},[114,11014,11015,11018,11020,11022],{"class":644,"line":832},[114,11016,11017],{"class":1166},"    uptimeSeconds",[114,11019,1170],{"class":735},[114,11021,3506],{"class":647},[114,11023,1098],{"class":735},[114,11025,11026],{"class":644,"line":891},[114,11027,1611],{"class":735},[114,11029,11030],{"class":644,"line":1204},[114,11031,879],{"class":735},[114,11033,11034],{"class":644,"line":1209},[114,11035,856],{"emptyLinePlaceholder":551},[114,11037,11038,11040,11043,11046],{"class":644,"line":1215},[114,11039,1152],{"class":1080},[114,11041,11042],{"class":1107}," class",[114,11044,11045],{"class":647}," KiroClient",[114,11047,1161],{"class":735},[114,11049,11050,11053,11056,11058,11060],{"class":644,"line":1221},[114,11051,11052],{"class":1107},"  private",[114,11054,11055],{"class":1166}," baseUrl",[114,11057,1170],{"class":735},[114,11059,1173],{"class":647},[114,11061,1098],{"class":735},[114,11063,11064,11066,11069,11071,11073],{"class":644,"line":1227},[114,11065,11052],{"class":1107},[114,11067,11068],{"class":1166}," apiKey",[114,11070,1170],{"class":735},[114,11072,1173],{"class":647},[114,11074,1098],{"class":735},[114,11076,11077],{"class":644,"line":1267},[114,11078,856],{"emptyLinePlaceholder":551},[114,11080,11081,11084,11086,11089,11091,11093,11095,11097,11099,11101,11104,11106,11108],{"class":644,"line":1305},[114,11082,11083],{"class":1107},"  constructor",[114,11085,1239],{"class":735},[114,11087,11088],{"class":1242},"apiKey",[114,11090,1170],{"class":735},[114,11092,1173],{"class":647},[114,11094,1250],{"class":735},[114,11096,11055],{"class":1242},[114,11098,1276],{"class":735},[114,11100,1090],{"class":735},[114,11102,11103],{"class":651},"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1",[114,11105,1095],{"class":735},[114,11107,1300],{"class":735},[114,11109,1161],{"class":735},[114,11111,11112,11115,11117,11119,11121],{"class":644,"line":1333},[114,11113,11114],{"class":735},"    this.",[114,11116,11088],{"class":745},[114,11118,1276],{"class":735},[114,11120,11068],{"class":745},[114,11122,1098],{"class":735},[114,11124,11125,11127,11130,11132,11134],{"class":644,"line":1358},[114,11126,11114],{"class":735},[114,11128,11129],{"class":745},"baseUrl",[114,11131,1276],{"class":735},[114,11133,11055],{"class":745},[114,11135,1098],{"class":735},[114,11137,11138],{"class":644,"line":1363},[114,11139,817],{"class":735},[114,11141,11142],{"class":644,"line":1368},[114,11143,856],{"emptyLinePlaceholder":551},[114,11145,11146,11148,11150,11153,11155,11157,11159,11162,11164,11166,11168,11171,11173,11175,11177,11180,11183,11186,11188,11190,11192,11194,11196],{"class":644,"line":1374},[114,11147,11052],{"class":1107},[114,11149,4354],{"class":1107},[114,11151,11152],{"class":1166}," request",[114,11154,3499],{"class":735},[114,11156,4786],{"class":647},[114,11158,4789],{"class":735},[114,11160,11161],{"class":1242},"method",[114,11163,1170],{"class":735},[114,11165,1173],{"class":647},[114,11167,1250],{"class":735},[114,11169,11170],{"class":1242}," endpoint",[114,11172,1170],{"class":735},[114,11174,1173],{"class":647},[114,11176,1250],{"class":735},[114,11178,11179],{"class":1242}," body",[114,11181,11182],{"class":735},"?:",[114,11184,11185],{"class":647}," unknown",[114,11187,1260],{"class":735},[114,11189,4801],{"class":647},[114,11191,3499],{"class":735},[114,11193,4786],{"class":647},[114,11195,3509],{"class":735},[114,11197,1161],{"class":735},[114,11199,11200,11202,11205,11207,11210,11212,11214,11216,11218,11220,11222],{"class":644,"line":1401},[114,11201,6505],{"class":1107},[114,11203,11204],{"class":745}," headers",[114,11206,1170],{"class":735},[114,11208,11209],{"class":647}," Record",[114,11211,3499],{"class":735},[114,11213,8837],{"class":647},[114,11215,1250],{"class":735},[114,11217,1173],{"class":647},[114,11219,3509],{"class":735},[114,11221,1276],{"class":735},[114,11223,1161],{"class":735},[114,11225,11226,11229,11231,11233,11235,11237,11240,11242,11245,11247,11249],{"class":644,"line":1435},[114,11227,11228],{"class":735},"      '",[114,11230,632],{"class":1166},[114,11232,1095],{"class":735},[114,11234,1170],{"class":735},[114,11236,2774],{"class":735},[114,11238,11239],{"class":651},"Bearer ",[114,11241,2657],{"class":735},[114,11243,11244],{"class":735},"this.",[114,11246,11088],{"class":745},[114,11248,2933],{"class":735},[114,11250,1571],{"class":735},[114,11252,11253,11255,11258,11260,11262,11264,11267,11269],{"class":644,"line":1440},[114,11254,11228],{"class":735},[114,11256,11257],{"class":1166},"Content-Type",[114,11259,1095],{"class":735},[114,11261,1170],{"class":735},[114,11263,1090],{"class":735},[114,11265,11266],{"class":651},"application\u002Fjson",[114,11268,1095],{"class":735},[114,11270,1571],{"class":735},[114,11272,11273,11275,11278,11280,11282,11284,11286,11288],{"class":644,"line":1483},[114,11274,11228],{"class":735},[114,11276,11277],{"class":1166},"Accept",[114,11279,1095],{"class":735},[114,11281,1170],{"class":735},[114,11283,1090],{"class":735},[114,11285,11266],{"class":651},[114,11287,1095],{"class":735},[114,11289,1571],{"class":735},[114,11291,11292],{"class":644,"line":1510},[114,11293,4520],{"class":735},[114,11295,11296],{"class":644,"line":1515},[114,11297,856],{"emptyLinePlaceholder":551},[114,11299,11300,11302,11305,11307,11309,11312,11314,11317,11319,11321,11324,11327,11329,11331],{"class":644,"line":1552},[114,11301,6505],{"class":1107},[114,11303,11304],{"class":745}," response",[114,11306,1276],{"class":735},[114,11308,4383],{"class":1080},[114,11310,11311],{"class":1235}," fetch",[114,11313,1239],{"class":1166},[114,11315,11316],{"class":735},"`${",[114,11318,11244],{"class":735},[114,11320,11129],{"class":745},[114,11322,11323],{"class":735},"}${",[114,11325,11326],{"class":745},"endpoint",[114,11328,2933],{"class":735},[114,11330,1250],{"class":735},[114,11332,1161],{"class":735},[114,11334,11335,11338],{"class":644,"line":1557},[114,11336,11337],{"class":745},"      method",[114,11339,1571],{"class":735},[114,11341,11342,11345],{"class":644,"line":1565},[114,11343,11344],{"class":745},"      headers",[114,11346,1571],{"class":735},[114,11348,11349,11352,11354,11356,11358,11360,11362,11364,11366,11369,11371,11373],{"class":644,"line":1574},[114,11350,11351],{"class":1166},"      body",[114,11353,1170],{"class":735},[114,11355,11179],{"class":745},[114,11357,10470],{"class":735},[114,11359,6282],{"class":745},[114,11361,50],{"class":735},[114,11363,6287],{"class":1235},[114,11365,1239],{"class":1166},[114,11367,11368],{"class":745},"body",[114,11370,1327],{"class":1166},[114,11372,1170],{"class":735},[114,11374,11375],{"class":735}," undefined,\n",[114,11377,11378,11380,11382],{"class":644,"line":1600},[114,11379,4886],{"class":735},[114,11381,1300],{"class":1166},[114,11383,1098],{"class":735},[114,11385,11386],{"class":644,"line":1608},[114,11387,856],{"emptyLinePlaceholder":551},[114,11389,11390,11392,11394,11396,11399,11401,11404,11406],{"class":644,"line":1614},[114,11391,9215],{"class":1080},[114,11393,257],{"class":1166},[114,11395,9622],{"class":735},[114,11397,11398],{"class":745},"response",[114,11400,50],{"class":735},[114,11402,11403],{"class":745},"ok",[114,11405,1327],{"class":1166},[114,11407,1330],{"class":735},[114,11409,11410,11412,11415,11417,11419,11421,11423,11425,11427,11429,11431,11433,11435,11437,11439,11442,11444],{"class":644,"line":1619},[114,11411,8245],{"class":1107},[114,11413,11414],{"class":745}," errorData",[114,11416,1276],{"class":735},[114,11418,4383],{"class":1080},[114,11420,11304],{"class":745},[114,11422,50],{"class":735},[114,11424,7611],{"class":1235},[114,11426,1532],{"class":1166},[114,11428,50],{"class":735},[114,11430,4259],{"class":1235},[114,11432,1239],{"class":1166},[114,11434,1532],{"class":735},[114,11436,2478],{"class":1107},[114,11438,257],{"class":1166},[114,11440,11441],{"class":735},"{}",[114,11443,5036],{"class":1166},[114,11445,1098],{"class":735},[114,11447,11448,11451,11453,11455,11457,11459,11462,11464,11466,11468,11470,11472,11475,11477,11480,11482,11485,11487,11489,11491,11494,11496,11498],{"class":644,"line":1624},[114,11449,11450],{"class":1080},"      throw",[114,11452,1339],{"class":735},[114,11454,1342],{"class":1235},[114,11456,1239],{"class":1166},[114,11458,2651],{"class":735},[114,11460,11461],{"class":651},"KiroCloud API Error [",[114,11463,2657],{"class":735},[114,11465,11398],{"class":745},[114,11467,50],{"class":735},[114,11469,4916],{"class":745},[114,11471,2693],{"class":735},[114,11473,11474],{"class":651},"]: ",[114,11476,2657],{"class":735},[114,11478,11479],{"class":745},"errorData",[114,11481,50],{"class":735},[114,11483,11484],{"class":745},"message ",[114,11486,9836],{"class":735},[114,11488,11304],{"class":745},[114,11490,50],{"class":735},[114,11492,11493],{"class":745},"statusText",[114,11495,2933],{"class":735},[114,11497,1300],{"class":1166},[114,11499,1098],{"class":735},[114,11501,11502],{"class":644,"line":1629},[114,11503,5076],{"class":735},[114,11505,11506],{"class":644,"line":1635},[114,11507,856],{"emptyLinePlaceholder":551},[114,11509,11510,11512,11514,11516,11518,11520,11523,11525,11527,11529],{"class":644,"line":1640},[114,11511,4407],{"class":1080},[114,11513,11304],{"class":745},[114,11515,50],{"class":735},[114,11517,7611],{"class":1235},[114,11519,3574],{"class":1166},[114,11521,11522],{"class":1080},"as",[114,11524,4801],{"class":647},[114,11526,3499],{"class":735},[114,11528,4786],{"class":647},[114,11530,11531],{"class":735},">;\n",[114,11533,11534],{"class":644,"line":1673},[114,11535,817],{"class":735},[114,11537,11538],{"class":644,"line":1704},[114,11539,856],{"emptyLinePlaceholder":551},[114,11541,11542],{"class":644,"line":1740},[114,11543,11544],{"class":1142},"  \u002F\u002F --- Public Status & Platform Health ---\n",[114,11546,11547],{"class":644,"line":1775},[114,11548,856],{"emptyLinePlaceholder":551},[114,11550,11551,11554,11557,11559],{"class":644,"line":1780},[114,11552,11553],{"class":1107},"  async",[114,11555,11556],{"class":1166}," getPlatformStatus",[114,11558,1532],{"class":735},[114,11560,1161],{"class":735},[114,11562,11563,11565,11568,11571,11573,11576,11578,11580,11582,11584,11586,11588,11590,11592,11594,11596,11598,11600,11602,11604,11607,11609,11611,11613,11616,11618,11620],{"class":644,"line":1813},[114,11564,4407],{"class":1080},[114,11566,11567],{"class":735}," this.",[114,11569,11570],{"class":1235},"request",[114,11572,10064],{"class":735},[114,11574,11575],{"class":1166}," success",[114,11577,1170],{"class":735},[114,11579,10556],{"class":647},[114,11581,1139],{"class":735},[114,11583,6508],{"class":1166},[114,11585,1170],{"class":735},[114,11587,11209],{"class":647},[114,11589,3499],{"class":735},[114,11591,8837],{"class":647},[114,11593,1250],{"class":735},[114,11595,11185],{"class":647},[114,11597,3509],{"class":735},[114,11599,10199],{"class":735},[114,11601,1239],{"class":1166},[114,11603,1095],{"class":735},[114,11605,11606],{"class":651},"GET",[114,11608,1095],{"class":735},[114,11610,1250],{"class":735},[114,11612,1090],{"class":735},[114,11614,11615],{"class":651},"\u002Fpublic\u002Fstatus",[114,11617,1095],{"class":735},[114,11619,1300],{"class":1166},[114,11621,1098],{"class":735},[114,11623,11624],{"class":644,"line":1832},[114,11625,817],{"class":735},[114,11627,11628],{"class":644,"line":1837},[114,11629,856],{"emptyLinePlaceholder":551},[114,11631,11632,11634,11637,11639],{"class":644,"line":1882},[114,11633,11553],{"class":1107},[114,11635,11636],{"class":1166}," getPlatformStats",[114,11638,1532],{"class":735},[114,11640,1161],{"class":735},[114,11642,11643,11645,11647,11649,11651,11653,11655,11657,11659,11661,11663,11665,11668,11670,11672,11674,11677,11679,11681,11683,11686,11688,11690,11692,11694,11696,11698,11700,11702,11704,11706,11709,11711,11713],{"class":644,"line":1911},[114,11644,4407],{"class":1080},[114,11646,11567],{"class":735},[114,11648,11570],{"class":1235},[114,11650,10064],{"class":735},[114,11652,11575],{"class":1166},[114,11654,1170],{"class":735},[114,11656,10556],{"class":647},[114,11658,1139],{"class":735},[114,11660,6508],{"class":1166},[114,11662,1170],{"class":735},[114,11664,3035],{"class":735},[114,11666,11667],{"class":1166}," activeBots",[114,11669,1170],{"class":735},[114,11671,3506],{"class":647},[114,11673,1139],{"class":735},[114,11675,11676],{"class":1166}," activeServers",[114,11678,1170],{"class":735},[114,11680,3506],{"class":647},[114,11682,1139],{"class":735},[114,11684,11685],{"class":1166}," uptime",[114,11687,1170],{"class":735},[114,11689,3506],{"class":647},[114,11691,3050],{"class":735},[114,11693,10199],{"class":735},[114,11695,1239],{"class":1166},[114,11697,1095],{"class":735},[114,11699,11606],{"class":651},[114,11701,1095],{"class":735},[114,11703,1250],{"class":735},[114,11705,1090],{"class":735},[114,11707,11708],{"class":651},"\u002Fpublic\u002Fstats",[114,11710,1095],{"class":735},[114,11712,1300],{"class":1166},[114,11714,1098],{"class":735},[114,11716,11717],{"class":644,"line":1916},[114,11718,817],{"class":735},[114,11720,11721],{"class":644,"line":1925},[114,11722,856],{"emptyLinePlaceholder":551},[114,11724,11726],{"class":644,"line":11725},53,[114,11727,11728],{"class":1142},"  \u002F\u002F --- Bot Management (Scope: bots:read, bots:write) ---\n",[114,11730,11732],{"class":644,"line":11731},54,[114,11733,856],{"emptyLinePlaceholder":551},[114,11735,11737,11739,11742,11744],{"class":644,"line":11736},55,[114,11738,11553],{"class":1107},[114,11740,11741],{"class":1166}," listBots",[114,11743,1532],{"class":735},[114,11745,1161],{"class":735},[114,11747,11749,11751,11753,11755,11757,11759,11761,11763,11765,11767,11769,11771,11773,11776,11778,11780,11782,11784,11786,11788,11790,11793,11795,11797,11799,11801,11803,11805,11807,11809,11811,11813,11816,11818,11820],{"class":644,"line":11748},56,[114,11750,4407],{"class":1080},[114,11752,11567],{"class":735},[114,11754,11570],{"class":1235},[114,11756,10064],{"class":735},[114,11758,11575],{"class":1166},[114,11760,1170],{"class":735},[114,11762,10556],{"class":647},[114,11764,1139],{"class":735},[114,11766,6508],{"class":1166},[114,11768,1170],{"class":735},[114,11770,10180],{"class":647},[114,11772,10064],{"class":735},[114,11774,11775],{"class":1166}," id",[114,11777,1170],{"class":735},[114,11779,1173],{"class":647},[114,11781,1139],{"class":735},[114,11783,9686],{"class":1166},[114,11785,1170],{"class":735},[114,11787,1173],{"class":647},[114,11789,1139],{"class":735},[114,11791,11792],{"class":1166}," status",[114,11794,1170],{"class":735},[114,11796,1173],{"class":647},[114,11798,10199],{"class":735},[114,11800,10199],{"class":735},[114,11802,1239],{"class":1166},[114,11804,1095],{"class":735},[114,11806,11606],{"class":651},[114,11808,1095],{"class":735},[114,11810,1250],{"class":735},[114,11812,1090],{"class":735},[114,11814,11815],{"class":651},"\u002Fbots",[114,11817,1095],{"class":735},[114,11819,1300],{"class":1166},[114,11821,1098],{"class":735},[114,11823,11825],{"class":644,"line":11824},57,[114,11826,817],{"class":735},[114,11828,11830],{"class":644,"line":11829},58,[114,11831,856],{"emptyLinePlaceholder":551},[114,11833,11835,11837,11840,11842,11844,11846,11848,11850],{"class":644,"line":11834},59,[114,11836,11553],{"class":1107},[114,11838,11839],{"class":1166}," getBot",[114,11841,1239],{"class":735},[114,11843,5757],{"class":1242},[114,11845,1170],{"class":735},[114,11847,1173],{"class":647},[114,11849,1300],{"class":735},[114,11851,1161],{"class":735},[114,11853,11855,11857,11859,11861,11863,11866,11868,11870,11872,11874,11876,11878,11880,11883,11885,11887,11889,11891],{"class":644,"line":11854},60,[114,11856,4407],{"class":1080},[114,11858,11567],{"class":735},[114,11860,11570],{"class":1235},[114,11862,3499],{"class":735},[114,11864,11865],{"class":647},"BotStatusResponse",[114,11867,3509],{"class":735},[114,11869,1239],{"class":1166},[114,11871,1095],{"class":735},[114,11873,11606],{"class":651},[114,11875,1095],{"class":735},[114,11877,1250],{"class":735},[114,11879,2774],{"class":735},[114,11881,11882],{"class":651},"\u002Fbots\u002F",[114,11884,2657],{"class":735},[114,11886,5757],{"class":745},[114,11888,2933],{"class":735},[114,11890,1300],{"class":1166},[114,11892,1098],{"class":735},[114,11894,11896],{"class":644,"line":11895},61,[114,11897,817],{"class":735},[114,11899,11901],{"class":644,"line":11900},62,[114,11902,856],{"emptyLinePlaceholder":551},[114,11904,11906,11908,11911,11913,11915,11917,11919,11921],{"class":644,"line":11905},63,[114,11907,11553],{"class":1107},[114,11909,11910],{"class":1166}," startBot",[114,11912,1239],{"class":735},[114,11914,5757],{"class":1242},[114,11916,1170],{"class":735},[114,11918,1173],{"class":647},[114,11920,1300],{"class":735},[114,11922,1161],{"class":735},[114,11924,11926,11928,11930,11932,11934,11936,11938,11940,11942,11944,11946,11948,11950,11952,11954,11957,11959,11961,11963,11965,11967,11969,11971,11974,11976,11978],{"class":644,"line":11925},64,[114,11927,4407],{"class":1080},[114,11929,11567],{"class":735},[114,11931,11570],{"class":1235},[114,11933,10064],{"class":735},[114,11935,11575],{"class":1166},[114,11937,1170],{"class":735},[114,11939,10556],{"class":647},[114,11941,1139],{"class":735},[114,11943,6474],{"class":1166},[114,11945,1170],{"class":735},[114,11947,1173],{"class":647},[114,11949,10199],{"class":735},[114,11951,1239],{"class":1166},[114,11953,1095],{"class":735},[114,11955,11956],{"class":651},"POST",[114,11958,1095],{"class":735},[114,11960,1250],{"class":735},[114,11962,2774],{"class":735},[114,11964,11882],{"class":651},[114,11966,2657],{"class":735},[114,11968,5757],{"class":745},[114,11970,2693],{"class":735},[114,11972,11973],{"class":651},"\u002Fstart",[114,11975,2651],{"class":735},[114,11977,1300],{"class":1166},[114,11979,1098],{"class":735},[114,11981,11983],{"class":644,"line":11982},65,[114,11984,817],{"class":735},[114,11986,11988],{"class":644,"line":11987},66,[114,11989,856],{"emptyLinePlaceholder":551},[114,11991,11993,11995,11998,12000,12002,12004,12006,12008],{"class":644,"line":11992},67,[114,11994,11553],{"class":1107},[114,11996,11997],{"class":1166}," stopBot",[114,11999,1239],{"class":735},[114,12001,5757],{"class":1242},[114,12003,1170],{"class":735},[114,12005,1173],{"class":647},[114,12007,1300],{"class":735},[114,12009,1161],{"class":735},[114,12011,12013,12015,12017,12019,12021,12023,12025,12027,12029,12031,12033,12035,12037,12039,12041,12043,12045,12047,12049,12051,12053,12055,12057,12060,12062,12064],{"class":644,"line":12012},68,[114,12014,4407],{"class":1080},[114,12016,11567],{"class":735},[114,12018,11570],{"class":1235},[114,12020,10064],{"class":735},[114,12022,11575],{"class":1166},[114,12024,1170],{"class":735},[114,12026,10556],{"class":647},[114,12028,1139],{"class":735},[114,12030,6474],{"class":1166},[114,12032,1170],{"class":735},[114,12034,1173],{"class":647},[114,12036,10199],{"class":735},[114,12038,1239],{"class":1166},[114,12040,1095],{"class":735},[114,12042,11956],{"class":651},[114,12044,1095],{"class":735},[114,12046,1250],{"class":735},[114,12048,2774],{"class":735},[114,12050,11882],{"class":651},[114,12052,2657],{"class":735},[114,12054,5757],{"class":745},[114,12056,2693],{"class":735},[114,12058,12059],{"class":651},"\u002Fstop",[114,12061,2651],{"class":735},[114,12063,1300],{"class":1166},[114,12065,1098],{"class":735},[114,12067,12069],{"class":644,"line":12068},69,[114,12070,817],{"class":735},[114,12072,12074],{"class":644,"line":12073},70,[114,12075,856],{"emptyLinePlaceholder":551},[114,12077,12079,12081,12084,12086,12088,12090,12092,12094],{"class":644,"line":12078},71,[114,12080,11553],{"class":1107},[114,12082,12083],{"class":1166}," restartBot",[114,12085,1239],{"class":735},[114,12087,5757],{"class":1242},[114,12089,1170],{"class":735},[114,12091,1173],{"class":647},[114,12093,1300],{"class":735},[114,12095,1161],{"class":735},[114,12097,12099,12101,12103,12105,12107,12109,12111,12113,12115,12117,12119,12121,12123,12125,12127,12129,12131,12133,12135,12137,12139,12141,12143,12146,12148,12150],{"class":644,"line":12098},72,[114,12100,4407],{"class":1080},[114,12102,11567],{"class":735},[114,12104,11570],{"class":1235},[114,12106,10064],{"class":735},[114,12108,11575],{"class":1166},[114,12110,1170],{"class":735},[114,12112,10556],{"class":647},[114,12114,1139],{"class":735},[114,12116,6474],{"class":1166},[114,12118,1170],{"class":735},[114,12120,1173],{"class":647},[114,12122,10199],{"class":735},[114,12124,1239],{"class":1166},[114,12126,1095],{"class":735},[114,12128,11956],{"class":651},[114,12130,1095],{"class":735},[114,12132,1250],{"class":735},[114,12134,2774],{"class":735},[114,12136,11882],{"class":651},[114,12138,2657],{"class":735},[114,12140,5757],{"class":745},[114,12142,2693],{"class":735},[114,12144,12145],{"class":651},"\u002Frestart",[114,12147,2651],{"class":735},[114,12149,1300],{"class":1166},[114,12151,1098],{"class":735},[114,12153,12155],{"class":644,"line":12154},73,[114,12156,817],{"class":735},[114,12158,12160],{"class":644,"line":12159},74,[114,12161,856],{"emptyLinePlaceholder":551},[114,12163,12165,12167,12170,12172,12174,12176,12178,12180,12183,12185,12187,12190,12192,12194,12196,12199,12201,12203,12205,12207,12209,12211,12213,12216],{"class":644,"line":12164},75,[114,12166,11553],{"class":1107},[114,12168,12169],{"class":1166}," sendEmbed",[114,12171,1239],{"class":735},[114,12173,5757],{"class":1242},[114,12175,1170],{"class":735},[114,12177,1173],{"class":647},[114,12179,1250],{"class":735},[114,12181,12182],{"class":1242}," payload",[114,12184,1170],{"class":735},[114,12186,3035],{"class":735},[114,12188,12189],{"class":1166}," channelId",[114,12191,1170],{"class":735},[114,12193,1173],{"class":647},[114,12195,1139],{"class":735},[114,12197,12198],{"class":1166}," embed",[114,12200,1170],{"class":735},[114,12202,11209],{"class":647},[114,12204,3499],{"class":735},[114,12206,8837],{"class":647},[114,12208,1250],{"class":735},[114,12210,11185],{"class":647},[114,12212,3509],{"class":735},[114,12214,12215],{"class":735}," })",[114,12217,1161],{"class":735},[114,12219,12221,12223,12225,12227,12229,12231,12233,12235,12237,12240,12242,12244,12246,12248,12250,12252,12254,12256,12258,12260,12262,12264,12266,12269,12271,12273,12275,12277],{"class":644,"line":12220},76,[114,12222,4407],{"class":1080},[114,12224,11567],{"class":735},[114,12226,11570],{"class":1235},[114,12228,10064],{"class":735},[114,12230,11575],{"class":1166},[114,12232,1170],{"class":735},[114,12234,10556],{"class":647},[114,12236,1139],{"class":735},[114,12238,12239],{"class":1166}," messageId",[114,12241,1170],{"class":735},[114,12243,1173],{"class":647},[114,12245,10199],{"class":735},[114,12247,1239],{"class":1166},[114,12249,1095],{"class":735},[114,12251,11956],{"class":651},[114,12253,1095],{"class":735},[114,12255,1250],{"class":735},[114,12257,2774],{"class":735},[114,12259,11882],{"class":651},[114,12261,2657],{"class":735},[114,12263,5757],{"class":745},[114,12265,2693],{"class":735},[114,12267,12268],{"class":651},"\u002Fsend-embed",[114,12270,2651],{"class":735},[114,12272,1250],{"class":735},[114,12274,12182],{"class":745},[114,12276,1300],{"class":1166},[114,12278,1098],{"class":735},[114,12280,12282],{"class":644,"line":12281},77,[114,12283,817],{"class":735},[114,12285,12287],{"class":644,"line":12286},78,[114,12288,856],{"emptyLinePlaceholder":551},[114,12290,12292],{"class":644,"line":12291},79,[114,12293,12294],{"class":1142},"  \u002F\u002F --- Support Tickets (Scope: tickets:read, tickets:write) ---\n",[114,12296,12298],{"class":644,"line":12297},80,[114,12299,856],{"emptyLinePlaceholder":551},[114,12301,12303,12305,12308,12310],{"class":644,"line":12302},81,[114,12304,11553],{"class":1107},[114,12306,12307],{"class":1166}," listTickets",[114,12309,1532],{"class":735},[114,12311,1161],{"class":735},[114,12313,12315,12317,12319,12321,12323,12325,12327,12329,12331,12333,12335,12337,12339,12341,12343,12345,12347,12350,12352,12354,12356,12358,12360,12362,12364,12366,12368,12370,12372,12374,12376,12378,12381,12383,12385],{"class":644,"line":12314},82,[114,12316,4407],{"class":1080},[114,12318,11567],{"class":735},[114,12320,11570],{"class":1235},[114,12322,10064],{"class":735},[114,12324,11575],{"class":1166},[114,12326,1170],{"class":735},[114,12328,10556],{"class":647},[114,12330,1139],{"class":735},[114,12332,6508],{"class":1166},[114,12334,1170],{"class":735},[114,12336,10180],{"class":647},[114,12338,10064],{"class":735},[114,12340,11775],{"class":1166},[114,12342,1170],{"class":735},[114,12344,1173],{"class":647},[114,12346,1139],{"class":735},[114,12348,12349],{"class":1166}," subject",[114,12351,1170],{"class":735},[114,12353,1173],{"class":647},[114,12355,1139],{"class":735},[114,12357,11792],{"class":1166},[114,12359,1170],{"class":735},[114,12361,1173],{"class":647},[114,12363,10199],{"class":735},[114,12365,10199],{"class":735},[114,12367,1239],{"class":1166},[114,12369,1095],{"class":735},[114,12371,11606],{"class":651},[114,12373,1095],{"class":735},[114,12375,1250],{"class":735},[114,12377,1090],{"class":735},[114,12379,12380],{"class":651},"\u002Ftickets",[114,12382,1095],{"class":735},[114,12384,1300],{"class":1166},[114,12386,1098],{"class":735},[114,12388,12390],{"class":644,"line":12389},83,[114,12391,817],{"class":735},[114,12393,12395],{"class":644,"line":12394},84,[114,12396,856],{"emptyLinePlaceholder":551},[114,12398,12400,12402,12405,12407,12410,12412,12414,12416,12418,12420,12422,12424,12426,12428,12430,12433,12435,12437,12440,12442,12444,12446,12449,12451,12453,12455,12458,12460,12462],{"class":644,"line":12399},85,[114,12401,11553],{"class":1107},[114,12403,12404],{"class":1166}," createTicket",[114,12406,1239],{"class":735},[114,12408,12409],{"class":1242},"payload",[114,12411,1170],{"class":735},[114,12413,3035],{"class":735},[114,12415,12349],{"class":1166},[114,12417,1170],{"class":735},[114,12419,1173],{"class":647},[114,12421,1139],{"class":735},[114,12423,6474],{"class":1166},[114,12425,1170],{"class":735},[114,12427,1173],{"class":647},[114,12429,1139],{"class":735},[114,12431,12432],{"class":1166}," priority",[114,12434,11182],{"class":735},[114,12436,1090],{"class":735},[114,12438,12439],{"class":651},"low",[114,12441,1095],{"class":735},[114,12443,10391],{"class":735},[114,12445,1090],{"class":735},[114,12447,12448],{"class":651},"normal",[114,12450,1095],{"class":735},[114,12452,10391],{"class":735},[114,12454,1090],{"class":735},[114,12456,12457],{"class":651},"high",[114,12459,1095],{"class":735},[114,12461,12215],{"class":735},[114,12463,1161],{"class":735},[114,12465,12467,12469,12471,12473,12475,12477,12479,12481,12483,12486,12488,12490,12492,12494,12496,12498,12500,12502,12504,12506,12508,12510,12512,12514],{"class":644,"line":12466},86,[114,12468,4407],{"class":1080},[114,12470,11567],{"class":735},[114,12472,11570],{"class":1235},[114,12474,10064],{"class":735},[114,12476,11575],{"class":1166},[114,12478,1170],{"class":735},[114,12480,10556],{"class":647},[114,12482,1139],{"class":735},[114,12484,12485],{"class":1166}," ticketId",[114,12487,1170],{"class":735},[114,12489,1173],{"class":647},[114,12491,10199],{"class":735},[114,12493,1239],{"class":1166},[114,12495,1095],{"class":735},[114,12497,11956],{"class":651},[114,12499,1095],{"class":735},[114,12501,1250],{"class":735},[114,12503,1090],{"class":735},[114,12505,12380],{"class":651},[114,12507,1095],{"class":735},[114,12509,1250],{"class":735},[114,12511,12182],{"class":745},[114,12513,1300],{"class":1166},[114,12515,1098],{"class":735},[114,12517,12519],{"class":644,"line":12518},87,[114,12520,817],{"class":735},[114,12522,12524],{"class":644,"line":12523},88,[114,12525,879],{"class":735},[29,12527],{},[714,12529,12531],{"id":12530},"_22-python-requests","2.2 Python (Requests)",[22,12533,12534,12535,1260],{},"Für Python-basierte Bots, Automatisierungen oder CLI-Werkzeuge (",[97,12536,12537],{},"pip install requests",[635,12539,12541],{"className":842,"code":12540,"language":844,"meta":7,"style":7},"# kiro_client.py\nimport requests\nfrom typing import Optional, Dict, Any, List\n\nclass KiroClient:\n    def __init__(self, api_key: str, base_url: str = \"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1\"):\n        self.api_key = api_key\n        self.base_url = base_url\n        self.headers = {\n            \"Authorization\": f\"Bearer {api_key}\",\n            \"Content-Type\": \"application\u002Fjson\",\n            \"Accept\": \"application\u002Fjson\",\n        }\n\n    def _request(self, method: str, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:\n        url = f\"{self.base_url}{endpoint}\"\n        resp = requests.request(method, url, headers=self.headers, json=data, timeout=10)\n        if not resp.ok:\n            raise Exception(f\"KiroCloud API Error [{resp.status_code}]: {resp.text}\")\n        return resp.json()\n\n    # --- System Status ---\n    def get_status(self) -> Dict[str, Any]:\n        return self._request(\"GET\", \"\u002Fpublic\u002Fstatus\")\n\n    def get_stats(self) -> Dict[str, Any]:\n        return self._request(\"GET\", \"\u002Fpublic\u002Fstats\")\n\n    # --- Bots ---\n    def list_bots(self) -> List[Dict[str, Any]]:\n        return self._request(\"GET\", \"\u002Fbots\").get(\"data\", [])\n\n    def get_bot(self, bot_id: str) -> Dict[str, Any]:\n        return self._request(\"GET\", f\"\u002Fbots\u002F{bot_id}\")\n\n    def restart_bot(self, bot_id: str) -> Dict[str, Any]:\n        return self._request(\"POST\", f\"\u002Fbots\u002F{bot_id}\u002Frestart\")\n\n    def send_embed(self, bot_id: str, channel_id: str, embed_data: Dict[str, Any]) -> Dict[str, Any]:\n        return self._request(\"POST\", f\"\u002Fbots\u002F{bot_id}\u002Fsend-embed\", {\n            \"channelId\": channel_id,\n            \"embed\": embed_data,\n        })\n",[97,12542,12543,12548,12552,12557,12561,12566,12571,12576,12581,12586,12591,12596,12601,12606,12610,12615,12620,12625,12630,12635,12640,12644,12649,12654,12659,12663,12668,12673,12677,12682,12687,12692,12696,12701,12706,12710,12715,12720,12724,12729,12734,12739,12744],{"__ignoreMap":7},[114,12544,12545],{"class":644,"line":552},[114,12546,12547],{},"# kiro_client.py\n",[114,12549,12550],{"class":644,"line":537},[114,12551,851],{},[114,12553,12554],{"class":644,"line":763},[114,12555,12556],{},"from typing import Optional, Dict, Any, List\n",[114,12558,12559],{"class":644,"line":802},[114,12560,856],{"emptyLinePlaceholder":551},[114,12562,12563],{"class":644,"line":808},[114,12564,12565],{},"class KiroClient:\n",[114,12567,12568],{"class":644,"line":814},[114,12569,12570],{},"    def __init__(self, api_key: str, base_url: str = \"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1\"):\n",[114,12572,12573],{"class":644,"line":820},[114,12574,12575],{},"        self.api_key = api_key\n",[114,12577,12578],{"class":644,"line":826},[114,12579,12580],{},"        self.base_url = base_url\n",[114,12582,12583],{"class":644,"line":832},[114,12584,12585],{},"        self.headers = {\n",[114,12587,12588],{"class":644,"line":891},[114,12589,12590],{},"            \"Authorization\": f\"Bearer {api_key}\",\n",[114,12592,12593],{"class":644,"line":1204},[114,12594,12595],{},"            \"Content-Type\": \"application\u002Fjson\",\n",[114,12597,12598],{"class":644,"line":1209},[114,12599,12600],{},"            \"Accept\": \"application\u002Fjson\",\n",[114,12602,12603],{"class":644,"line":1215},[114,12604,12605],{},"        }\n",[114,12607,12608],{"class":644,"line":1221},[114,12609,856],{"emptyLinePlaceholder":551},[114,12611,12612],{"class":644,"line":1227},[114,12613,12614],{},"    def _request(self, method: str, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:\n",[114,12616,12617],{"class":644,"line":1267},[114,12618,12619],{},"        url = f\"{self.base_url}{endpoint}\"\n",[114,12621,12622],{"class":644,"line":1305},[114,12623,12624],{},"        resp = requests.request(method, url, headers=self.headers, json=data, timeout=10)\n",[114,12626,12627],{"class":644,"line":1333},[114,12628,12629],{},"        if not resp.ok:\n",[114,12631,12632],{"class":644,"line":1358},[114,12633,12634],{},"            raise Exception(f\"KiroCloud API Error [{resp.status_code}]: {resp.text}\")\n",[114,12636,12637],{"class":644,"line":1363},[114,12638,12639],{},"        return resp.json()\n",[114,12641,12642],{"class":644,"line":1368},[114,12643,856],{"emptyLinePlaceholder":551},[114,12645,12646],{"class":644,"line":1374},[114,12647,12648],{},"    # --- System Status ---\n",[114,12650,12651],{"class":644,"line":1401},[114,12652,12653],{},"    def get_status(self) -> Dict[str, Any]:\n",[114,12655,12656],{"class":644,"line":1435},[114,12657,12658],{},"        return self._request(\"GET\", \"\u002Fpublic\u002Fstatus\")\n",[114,12660,12661],{"class":644,"line":1440},[114,12662,856],{"emptyLinePlaceholder":551},[114,12664,12665],{"class":644,"line":1483},[114,12666,12667],{},"    def get_stats(self) -> Dict[str, Any]:\n",[114,12669,12670],{"class":644,"line":1510},[114,12671,12672],{},"        return self._request(\"GET\", \"\u002Fpublic\u002Fstats\")\n",[114,12674,12675],{"class":644,"line":1515},[114,12676,856],{"emptyLinePlaceholder":551},[114,12678,12679],{"class":644,"line":1552},[114,12680,12681],{},"    # --- Bots ---\n",[114,12683,12684],{"class":644,"line":1557},[114,12685,12686],{},"    def list_bots(self) -> List[Dict[str, Any]]:\n",[114,12688,12689],{"class":644,"line":1565},[114,12690,12691],{},"        return self._request(\"GET\", \"\u002Fbots\").get(\"data\", [])\n",[114,12693,12694],{"class":644,"line":1574},[114,12695,856],{"emptyLinePlaceholder":551},[114,12697,12698],{"class":644,"line":1600},[114,12699,12700],{},"    def get_bot(self, bot_id: str) -> Dict[str, Any]:\n",[114,12702,12703],{"class":644,"line":1608},[114,12704,12705],{},"        return self._request(\"GET\", f\"\u002Fbots\u002F{bot_id}\")\n",[114,12707,12708],{"class":644,"line":1614},[114,12709,856],{"emptyLinePlaceholder":551},[114,12711,12712],{"class":644,"line":1619},[114,12713,12714],{},"    def restart_bot(self, bot_id: str) -> Dict[str, Any]:\n",[114,12716,12717],{"class":644,"line":1624},[114,12718,12719],{},"        return self._request(\"POST\", f\"\u002Fbots\u002F{bot_id}\u002Frestart\")\n",[114,12721,12722],{"class":644,"line":1629},[114,12723,856],{"emptyLinePlaceholder":551},[114,12725,12726],{"class":644,"line":1635},[114,12727,12728],{},"    def send_embed(self, bot_id: str, channel_id: str, embed_data: Dict[str, Any]) -> Dict[str, Any]:\n",[114,12730,12731],{"class":644,"line":1640},[114,12732,12733],{},"        return self._request(\"POST\", f\"\u002Fbots\u002F{bot_id}\u002Fsend-embed\", {\n",[114,12735,12736],{"class":644,"line":1673},[114,12737,12738],{},"            \"channelId\": channel_id,\n",[114,12740,12741],{"class":644,"line":1704},[114,12742,12743],{},"            \"embed\": embed_data,\n",[114,12745,12746],{"class":644,"line":1740},[114,12747,12748],{},"        })\n",[29,12750],{},[714,12752,12754],{"id":12753},"_23-shell-curl-cicd-automatisierung","2.3 Shell \u002F cURL (CI\u002FCD Automatisierung)",[22,12756,12757],{},"Für Deployment-Skripte oder automatisierte Neustarts nach GitHub Actions Builds:",[635,12759,12761],{"className":637,"code":12760,"language":639,"meta":7,"style":7},"#!\u002Fbin\u002Fbash\nset -euo pipefail\n\nAPI_KEY=\"kiro_sec_YOUR_API_KEY_HERE\"\nBASE_URL=\"https:\u002F\u002Fapi.kirocloud.de\u002Fapi\u002Fv1\"\nBOT_ID=\"00000000-0000-0000-0000-000000000000\"\n\necho \"Checking platform health...\"\ncurl -s -f -X GET \"$BASE_URL\u002Fpublic\u002Fstatus\" \\\n  -H \"Accept: application\u002Fjson\" | jq .\n\necho \"Restarting bot instance after deployment...\"\ncurl -s -f -X POST \"$BASE_URL\u002Fbots\u002F$BOT_ID\u002Frestart\" \\\n  -H \"Authorization: Bearer $API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" | jq .\n",[97,12762,12763,12768,12778,12782,12796,12809,12823,12827,12838,12863,12881,12885,12896,12924,12940],{"__ignoreMap":7},[114,12764,12765],{"class":644,"line":552},[114,12766,12767],{"class":1142},"#!\u002Fbin\u002Fbash\n",[114,12769,12770,12772,12775],{"class":644,"line":537},[114,12771,3558],{"class":1235},[114,12773,12774],{"class":651}," -euo",[114,12776,12777],{"class":651}," pipefail\n",[114,12779,12780],{"class":644,"line":763},[114,12781,856],{"emptyLinePlaceholder":551},[114,12783,12784,12787,12789,12791,12794],{"class":644,"line":802},[114,12785,12786],{"class":745},"API_KEY",[114,12788,1114],{"class":735},[114,12790,742],{"class":735},[114,12792,12793],{"class":651},"kiro_sec_YOUR_API_KEY_HERE",[114,12795,773],{"class":735},[114,12797,12798,12801,12803,12805,12807],{"class":644,"line":808},[114,12799,12800],{"class":745},"BASE_URL",[114,12802,1114],{"class":735},[114,12804,742],{"class":735},[114,12806,11103],{"class":651},[114,12808,773],{"class":735},[114,12810,12811,12814,12816,12818,12821],{"class":644,"line":814},[114,12812,12813],{"class":745},"BOT_ID",[114,12815,1114],{"class":735},[114,12817,742],{"class":735},[114,12819,12820],{"class":651},"00000000-0000-0000-0000-000000000000",[114,12822,773],{"class":735},[114,12824,12825],{"class":644,"line":820},[114,12826,856],{"emptyLinePlaceholder":551},[114,12828,12829,12831,12833,12836],{"class":644,"line":826},[114,12830,5584],{"class":1235},[114,12832,736],{"class":735},[114,12834,12835],{"class":651},"Checking platform health...",[114,12837,773],{"class":735},[114,12839,12840,12842,12845,12848,12850,12852,12854,12857,12859,12861],{"class":644,"line":832},[114,12841,716],{"class":647},[114,12843,12844],{"class":651}," -s",[114,12846,12847],{"class":651}," -f",[114,12849,729],{"class":651},[114,12851,732],{"class":651},[114,12853,736],{"class":735},[114,12855,12856],{"class":745},"$BASE_URL",[114,12858,11615],{"class":651},[114,12860,742],{"class":735},[114,12862,746],{"class":745},[114,12864,12865,12867,12869,12871,12873,12875,12878],{"class":644,"line":891},[114,12866,751],{"class":651},[114,12868,736],{"class":735},[114,12870,770],{"class":651},[114,12872,742],{"class":735},[114,12874,10391],{"class":735},[114,12876,12877],{"class":647}," jq",[114,12879,12880],{"class":651}," .\n",[114,12882,12883],{"class":644,"line":1204},[114,12884,856],{"emptyLinePlaceholder":551},[114,12886,12887,12889,12891,12894],{"class":644,"line":1209},[114,12888,5584],{"class":1235},[114,12890,736],{"class":735},[114,12892,12893],{"class":651},"Restarting bot instance after deployment...",[114,12895,773],{"class":735},[114,12897,12898,12900,12902,12904,12906,12909,12911,12913,12915,12918,12920,12922],{"class":644,"line":1215},[114,12899,716],{"class":647},[114,12901,12844],{"class":651},[114,12903,12847],{"class":651},[114,12905,729],{"class":651},[114,12907,12908],{"class":651}," POST",[114,12910,736],{"class":735},[114,12912,12856],{"class":745},[114,12914,11882],{"class":651},[114,12916,12917],{"class":745},"$BOT_ID",[114,12919,12145],{"class":651},[114,12921,742],{"class":735},[114,12923,746],{"class":745},[114,12925,12926,12928,12930,12933,12936,12938],{"class":644,"line":1221},[114,12927,751],{"class":651},[114,12929,736],{"class":735},[114,12931,12932],{"class":651},"Authorization: Bearer ",[114,12934,12935],{"class":745},"$API_KEY",[114,12937,742],{"class":735},[114,12939,746],{"class":745},[114,12941,12942,12944,12946,12949,12951,12953,12955],{"class":644,"line":1227},[114,12943,751],{"class":651},[114,12945,736],{"class":735},[114,12947,12948],{"class":651},"Content-Type: application\u002Fjson",[114,12950,742],{"class":735},[114,12952,10391],{"class":735},[114,12954,12877],{"class":647},[114,12956,12880],{"class":651},[29,12958],{},[32,12960,12962],{"id":12961},"_3-endpunkt-spezifikation","3. Endpunkt-Spezifikation",[714,12964,12966],{"id":12965},"_31-plattform-status-metriken-öffentlich","3.1 Plattform-Status & Metriken (Öffentlich)",[12968,12969,12971,12972],"h4",{"id":12970},"get-apiv1publicstatus","GET ",[97,12973,12974],{},"\u002Fapi\u002Fv1\u002Fpublic\u002Fstatus",[22,12976,12977],{},"Liefert den aktuellen Betriebszustand aller KiroCloud-Komponenten (Discord Gateway Proxies, Rechenknoten, Datenbank).",[40,12979,12980,12985],{},[43,12981,12982,12984],{},[47,12983,5432],{}," Keine erforderlich",[43,12986,12987,368,12990],{},[47,12988,12989],{},"Antwort:",[97,12991,12992],{},"200 OK",[635,12994,12996],{"className":7609,"code":12995,"language":7611,"meta":7,"style":7},"{\n  \"success\": true,\n  \"data\": {\n    \"overall\": \"operational\",\n    \"services\": {\n      \"database\": \"operational\",\n      \"botEngine\": \"operational\",\n      \"minecraftNodes\": \"operational\"\n    },\n    \"timestamp\": \"2026-10-09T00:00:00.000Z\"\n  }\n}\n",[97,12997,12998,13002,13016,13028,13048,13061,13081,13100,13117,13121,13139,13143],{"__ignoreMap":7},[114,12999,13000],{"class":644,"line":552},[114,13001,1330],{"class":735},[114,13003,13004,13006,13009,13011,13013],{"class":644,"line":537},[114,13005,8430],{"class":735},[114,13007,13008],{"class":1107},"success",[114,13010,742],{"class":735},[114,13012,1170],{"class":735},[114,13014,13015],{"class":735}," true,\n",[114,13017,13018,13020,13022,13024,13026],{"class":644,"line":763},[114,13019,8430],{"class":735},[114,13021,6550],{"class":1107},[114,13023,742],{"class":735},[114,13025,1170],{"class":735},[114,13027,1161],{"class":735},[114,13029,13030,13032,13035,13037,13039,13041,13044,13046],{"class":644,"line":802},[114,13031,8444],{"class":735},[114,13033,13034],{"class":647},"overall",[114,13036,742],{"class":735},[114,13038,1170],{"class":735},[114,13040,736],{"class":735},[114,13042,13043],{"class":651},"operational",[114,13045,742],{"class":735},[114,13047,1571],{"class":735},[114,13049,13050,13052,13055,13057,13059],{"class":644,"line":808},[114,13051,8444],{"class":735},[114,13053,13054],{"class":647},"services",[114,13056,742],{"class":735},[114,13058,1170],{"class":735},[114,13060,1161],{"class":735},[114,13062,13063,13066,13069,13071,13073,13075,13077,13079],{"class":644,"line":814},[114,13064,13065],{"class":735},"      \"",[114,13067,13068],{"class":1135},"database",[114,13070,742],{"class":735},[114,13072,1170],{"class":735},[114,13074,736],{"class":735},[114,13076,13043],{"class":651},[114,13078,742],{"class":735},[114,13080,1571],{"class":735},[114,13082,13083,13085,13088,13090,13092,13094,13096,13098],{"class":644,"line":820},[114,13084,13065],{"class":735},[114,13086,13087],{"class":1135},"botEngine",[114,13089,742],{"class":735},[114,13091,1170],{"class":735},[114,13093,736],{"class":735},[114,13095,13043],{"class":651},[114,13097,742],{"class":735},[114,13099,1571],{"class":735},[114,13101,13102,13104,13107,13109,13111,13113,13115],{"class":644,"line":826},[114,13103,13065],{"class":735},[114,13105,13106],{"class":1135},"minecraftNodes",[114,13108,742],{"class":735},[114,13110,1170],{"class":735},[114,13112,736],{"class":735},[114,13114,13043],{"class":651},[114,13116,773],{"class":735},[114,13118,13119],{"class":644,"line":832},[114,13120,3278],{"class":735},[114,13122,13123,13125,13128,13130,13132,13134,13137],{"class":644,"line":891},[114,13124,8444],{"class":735},[114,13126,13127],{"class":647},"timestamp",[114,13129,742],{"class":735},[114,13131,1170],{"class":735},[114,13133,736],{"class":735},[114,13135,13136],{"class":651},"2026-10-09T00:00:00.000Z",[114,13138,773],{"class":735},[114,13140,13141],{"class":644,"line":1204},[114,13142,817],{"class":735},[114,13144,13145],{"class":644,"line":1209},[114,13146,879],{"class":735},[12968,13148,12971,13150],{"id":13149},"get-apiv1publicstats",[97,13151,13152],{},"\u002Fapi\u002Fv1\u002Fpublic\u002Fstats",[22,13154,13155],{},"Aggregierte Echtzeit-Statistiken über die Gesamtlaufzeit und aktive Instanzen.",[40,13157,13158],{},[43,13159,13160,12984],{},[47,13161,5432],{},[29,13163],{},[714,13165,13167],{"id":13166},"_32-bot-steuerung-instanz-lifecycle","3.2 Bot-Steuerung & Instanz-Lifecycle",[12968,13169,12971,13171],{"id":13170},"get-apiv1bots",[97,13172,13173],{},"\u002Fapi\u002Fv1\u002Fbots",[22,13175,13176],{},"Gibt alle Bots zurück, die dem authentifizierten Benutzer-Account zugeordnet sind.",[40,13178,13179,13186],{},[43,13180,13181,368,13184],{},[47,13182,13183],{},"Scope:",[97,13185,669],{},[43,13187,13188,13190],{},[47,13189,12989],{}," Array von Bot-Metadaten (Name, Status, Laufzeitverfallsdatum).",[12968,13192,12971,13194],{"id":13193},"get-apiv1botsid",[97,13195,13196],{},"\u002Fapi\u002Fv1\u002Fbots\u002F:id",[22,13198,13199],{},"Ruft detaillierte Laufzeitdaten und Systemmetriken einer spezifischen Bot-Instanz ab.",[40,13201,13202],{},[43,13203,13204,368,13206],{},[47,13205,13183],{},[97,13207,669],{},[12968,13209,13211,13212],{"id":13210},"post-apiv1botsidstart","POST ",[97,13213,13214],{},"\u002Fapi\u002Fv1\u002Fbots\u002F:id\u002Fstart",[22,13216,13217],{},"Startet die isolierte Bot-Laufzeitumgebung in einer sicheren cgroups-Sandbox.",[40,13219,13220,13226],{},[43,13221,13222,368,13224],{},[47,13223,13183],{},[97,13225,675],{},[43,13227,13228,368,13231,13233],{},[47,13229,13230],{},"Rückgabe:",[97,13232,12992],{}," bei erfolgreicher Initialisierung.",[12968,13235,13211,13237],{"id":13236},"post-apiv1botsidstop",[97,13238,13239],{},"\u002Fapi\u002Fv1\u002Fbots\u002F:id\u002Fstop",[22,13241,13242,13243,13246],{},"Fährt den laufenden Node.js-Prozess des Bots kontrolliert über ",[97,13244,13245],{},"SIGTERM"," herunter.",[40,13248,13249],{},[43,13250,13251,368,13253],{},[47,13252,13183],{},[97,13254,675],{},[12968,13256,13211,13258],{"id":13257},"post-apiv1botsidrestart",[97,13259,13260],{},"\u002Fapi\u002Fv1\u002Fbots\u002F:id\u002Frestart",[22,13262,13263],{},"Führt einen kontrollierten Neustart der Instanz aus. Ideal nach dem Aktualisieren von Bot-Modulen oder Umgebungsvariablen.",[40,13265,13266],{},[43,13267,13268,368,13270],{},[47,13269,13183],{},[97,13271,675],{},[12968,13273,13211,13275],{"id":13274},"post-apiv1botsidsend-embed",[97,13276,13277],{},"\u002Fapi\u002Fv1\u002Fbots\u002F:id\u002Fsend-embed",[22,13279,13280],{},"Sendet ein gestaltetes Discord-Embed über den authentifizierten Bot in einen Zielkanal.",[40,13282,13283,13289],{},[43,13284,13285,368,13287],{},[47,13286,13183],{},[97,13288,675],{},[43,13290,13291],{},[47,13292,13293],{},"Payload:",[635,13295,13297],{"className":7609,"code":13296,"language":7611,"meta":7,"style":7},"{\n  \"channelId\": \"123456789012345678\",\n  \"embed\": {\n    \"title\": \"Wartungsarbeiten abgeschlossen\",\n    \"description\": \"Alle Systeme laufen wieder mit voller Leistung.\",\n    \"color\": 3447003\n  }\n}\n",[97,13298,13299,13303,13323,13336,13356,13376,13389,13393],{"__ignoreMap":7},[114,13300,13301],{"class":644,"line":552},[114,13302,1330],{"class":735},[114,13304,13305,13307,13310,13312,13314,13316,13319,13321],{"class":644,"line":537},[114,13306,8430],{"class":735},[114,13308,13309],{"class":1107},"channelId",[114,13311,742],{"class":735},[114,13313,1170],{"class":735},[114,13315,736],{"class":735},[114,13317,13318],{"class":651},"123456789012345678",[114,13320,742],{"class":735},[114,13322,1571],{"class":735},[114,13324,13325,13327,13330,13332,13334],{"class":644,"line":763},[114,13326,8430],{"class":735},[114,13328,13329],{"class":1107},"embed",[114,13331,742],{"class":735},[114,13333,1170],{"class":735},[114,13335,1161],{"class":735},[114,13337,13338,13340,13343,13345,13347,13349,13352,13354],{"class":644,"line":802},[114,13339,8444],{"class":735},[114,13341,13342],{"class":647},"title",[114,13344,742],{"class":735},[114,13346,1170],{"class":735},[114,13348,736],{"class":735},[114,13350,13351],{"class":651},"Wartungsarbeiten abgeschlossen",[114,13353,742],{"class":735},[114,13355,1571],{"class":735},[114,13357,13358,13360,13363,13365,13367,13369,13372,13374],{"class":644,"line":808},[114,13359,8444],{"class":735},[114,13361,13362],{"class":647},"description",[114,13364,742],{"class":735},[114,13366,1170],{"class":735},[114,13368,736],{"class":735},[114,13370,13371],{"class":651},"Alle Systeme laufen wieder mit voller Leistung.",[114,13373,742],{"class":735},[114,13375,1571],{"class":735},[114,13377,13378,13380,13382,13384,13386],{"class":644,"line":814},[114,13379,8444],{"class":735},[114,13381,7646],{"class":647},[114,13383,742],{"class":735},[114,13385,1170],{"class":735},[114,13387,13388],{"class":1135}," 3447003\n",[114,13390,13391],{"class":644,"line":820},[114,13392,817],{"class":735},[114,13394,13395],{"class":644,"line":826},[114,13396,879],{"class":735},[29,13398],{},[714,13400,13402],{"id":13401},"_33-support-ticket-api","3.3 Support-Ticket API",[12968,13404,12971,13406],{"id":13405},"get-apiv1tickets",[97,13407,13408],{},"\u002Fapi\u002Fv1\u002Ftickets",[22,13410,13411],{},"Listet alle eigenen Support-Tickets inklusive aktuellem Bearbeitungsstatus auf.",[40,13413,13414],{},[43,13415,13416,368,13418],{},[47,13417,13183],{},[97,13419,681],{},[12968,13421,13211,13423],{"id":13422},"post-apiv1tickets",[97,13424,13408],{},[22,13426,13427],{},"Eröffnet ein neues Support-Ticket im KiroCloud Helpdesk.",[40,13429,13430,13436],{},[43,13431,13432,368,13434],{},[47,13433,13183],{},[97,13435,687],{},[43,13437,13438],{},[47,13439,13293],{},[635,13441,13443],{"className":7609,"code":13442,"language":7611,"meta":7,"style":7},"{\n  \"subject\": \"Frage zur Bot-Skalierung\",\n  \"message\": \"Wie kann ich die Shard-Anzahl für meinen Bot dynamisch anpassen?\",\n  \"priority\": \"normal\"\n}\n",[97,13444,13445,13449,13469,13488,13505],{"__ignoreMap":7},[114,13446,13447],{"class":644,"line":552},[114,13448,1330],{"class":735},[114,13450,13451,13453,13456,13458,13460,13462,13465,13467],{"class":644,"line":537},[114,13452,8430],{"class":735},[114,13454,13455],{"class":1107},"subject",[114,13457,742],{"class":735},[114,13459,1170],{"class":735},[114,13461,736],{"class":735},[114,13463,13464],{"class":651},"Frage zur Bot-Skalierung",[114,13466,742],{"class":735},[114,13468,1571],{"class":735},[114,13470,13471,13473,13475,13477,13479,13481,13484,13486],{"class":644,"line":763},[114,13472,8430],{"class":735},[114,13474,2473],{"class":1107},[114,13476,742],{"class":735},[114,13478,1170],{"class":735},[114,13480,736],{"class":735},[114,13482,13483],{"class":651},"Wie kann ich die Shard-Anzahl für meinen Bot dynamisch anpassen?",[114,13485,742],{"class":735},[114,13487,1571],{"class":735},[114,13489,13490,13492,13495,13497,13499,13501,13503],{"class":644,"line":802},[114,13491,8430],{"class":735},[114,13493,13494],{"class":1107},"priority",[114,13496,742],{"class":735},[114,13498,1170],{"class":735},[114,13500,736],{"class":735},[114,13502,12448],{"class":651},[114,13504,773],{"class":735},[114,13506,13507],{"class":644,"line":808},[114,13508,879],{"class":735},[29,13510],{},[32,13512,13514],{"id":13513},"_4-http-statuscodes-fehlerbehandlung","4. HTTP-Statuscodes & Fehlerbehandlung",[22,13516,13517],{},"Die KiroCloud-API antwortet bei Fehlern stets mit standardisierten RFC-7807-konformen JSON-Objekten:",[447,13519,13520,13533],{},[450,13521,13522],{},[453,13523,13524,13527,13530],{},[456,13525,13526],{"align":458},"Statuscode",[456,13528,13529],{"align":458},"Fehler-Code",[456,13531,13532],{"align":458},"Ursache & Empfohlene Maßnahme",[467,13534,13535,13553,13570,13585,13603],{},[453,13536,13537,13541,13546],{},[472,13538,13539],{"align":458},[97,13540,919],{},[472,13542,13543],{"align":458},[97,13544,13545],{},"UNAUTHORIZED",[472,13547,13548,13549,13552],{"align":458},"Der API-Schlüssel fehlt, ist ungültig oder abgelaufen. Prüfe den ",[97,13550,13551],{},"Authorization: Bearer","-Header.",[453,13554,13555,13559,13564],{},[472,13556,13557],{"align":458},[97,13558,929],{},[472,13560,13561],{"align":458},[97,13562,13563],{},"FORBIDDEN_SCOPE",[472,13565,13566,13567,13569],{"align":458},"Dem Schlüssel fehlt die erforderliche Berechtigung (z. B. ",[97,13568,675],{}," für Neustarts).",[453,13571,13572,13577,13582],{},[472,13573,13574],{"align":458},[97,13575,13576],{},"404 Not Found",[472,13578,13579],{"align":458},[97,13580,13581],{},"NOT_FOUND",[472,13583,13584],{"align":458},"Die angefragte Ressource (Bot-ID oder Ticket) existiert nicht oder gehört einem anderen Account.",[453,13586,13587,13591,13596],{},[472,13588,13589],{"align":458},[97,13590,939],{},[472,13592,13593],{"align":458},[97,13594,13595],{},"RATE_LIMITED",[472,13597,13598,13599,13602],{"align":458},"Anfragelimit erreicht. Implementiere einen exponentiellen Backoff (",[97,13600,13601],{},"Retry-After","-Header beachten).",[453,13604,13605,13610,13615],{},[472,13606,13607],{"align":458},[97,13608,13609],{},"500 Internal Error",[472,13611,13612],{"align":458},[97,13613,13614],{},"INTERNAL_ERROR",[472,13616,13617],{"align":458},"Vorübergehender Serverfehler. Bitte an den Support wenden oder nach 5 Sekunden erneut versuchen.",[944,13619,13620],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":7,"searchDepth":537,"depth":537,"links":13622},[13623,13626,13631,13636],{"id":10840,"depth":537,"text":10841,"children":13624},[13625],{"id":10850,"depth":763,"text":10851},{"id":10885,"depth":537,"text":10886,"children":13627},[13628,13629,13630],{"id":10892,"depth":763,"text":10893},{"id":12530,"depth":763,"text":12531},{"id":12753,"depth":763,"text":12754},{"id":12961,"depth":537,"text":12962,"children":13632},[13633,13634,13635],{"id":12965,"depth":763,"text":12966},{"id":13166,"depth":763,"text":13167},{"id":13401,"depth":763,"text":13402},{"id":13513,"depth":537,"text":13514},"Offizielle REST-API-Referenz zur programmatischen Steuerung von Discord Bots, Tickets und Systemmetriken.",{"icon":13639},"i-lucide-code-2","\u002Fdocs\u002Fde\u002Frest-endpoints",{"title":10819,"description":13637},"docs\u002Fde\u002Frest-endpoints","7eq9LoeJn9at-f0zpuNsivdZsbyJ8Uk46Ygxf9fOm-U",{"id":13645,"title":13646,"author":12,"body":13647,"category":14014,"description":14015,"extension":549,"lastUpdated":12,"meta":14016,"navigation":551,"order":552,"path":14017,"readTime":12,"seo":14018,"stem":14019,"__hash__":14020},"docs\u002Fdocs\u002Fde\u002Fticket-system.md","Ticket-System",{"type":14,"value":13648,"toc":14001},[13649,13653,13656,13658,13662,13665,13669,13697,13741,13743,13747,13750,13826,13828,13832,13839,13843,13865,13869,13898,13900,13904,13907,13931,13933,13937,13940,13971,13973,13977,13980,13999],[17,13650,13652],{"id":13651},"ticket-system-professioneller-discord-support","Ticket-System: Professioneller Discord-Support",[22,13654,13655],{},"Das KiroCloud Ticket-System verwandelt deinen Discord-Server in eine vollwertige Helpdesk- und Kundensupport-Plattform. Deine Community-Mitglieder können per Knopfdruck oder Dropdown private Support-Kanäle öffnen, die automatisch den zuständigen Teammitgliedern zugewiesen werden.",[29,13657],{},[32,13659,13661],{"id":13660},"_1-einrichtung-support-panel","1. Einrichtung & Support-Panel",[22,13663,13664],{},"Um das Ticket-System für deinen Server bereitzustellen, sendest du ein interaktives Support-Panel in einen beliebigen Textkanal:",[714,13666,13668],{"id":13667},"support-panel-erstellen-und-senden","Support-Panel erstellen und senden:",[70,13670,13671,13677,13684,13694],{},[43,13672,13673,13674,50],{},"Navigiere im KiroCloud Bot-Dashboard zum Modul-Tab ",[47,13675,13676],{},"\"Tickets\"",[43,13678,13679,13680,13683],{},"Passe das Panel-Design im ",[47,13681,13682],{},"Universal Embed Builder"," an (Titel, Beschreibung, Embed-Farbe, Thumbnail und Banner).",[43,13685,13686,13687,13690,13691,13693],{},"Verwende die ",[47,13688,13689],{},"Panel-Leiste (SendPanelBar)"," im Dashboard oder gib als Administrator im Discord-Kanal den Befehl ",[97,13692,167],{}," ein.",[43,13695,13696],{},"KiroCloud postet ein ansprechendes Embed inklusive interaktiver Komponenten (Buttons oder Dropdown-Menü).",[635,13698,13700],{"className":5305,"code":13699,"language":5307,"meta":7,"style":7},"┌───────────────────────────────────────────────────────────┐\n│  [Support] Support & Hilfe Center                         │\n│                                                           │\n│  Wähle unten die passende Kategorie aus, um ein           │\n│  privates Ticket mit unserem Team zu eröffnen.            │\n│                                                           │\n│  [ Dropdown: Kategorie auswählen...              ▼ ]      │\n└───────────────────────────────────────────────────────────┘\n",[97,13701,13702,13707,13712,13717,13722,13727,13731,13736],{"__ignoreMap":7},[114,13703,13704],{"class":644,"line":552},[114,13705,13706],{},"┌───────────────────────────────────────────────────────────┐\n",[114,13708,13709],{"class":644,"line":537},[114,13710,13711],{},"│  [Support] Support & Hilfe Center                         │\n",[114,13713,13714],{"class":644,"line":763},[114,13715,13716],{},"│                                                           │\n",[114,13718,13719],{"class":644,"line":802},[114,13720,13721],{},"│  Wähle unten die passende Kategorie aus, um ein           │\n",[114,13723,13724],{"class":644,"line":808},[114,13725,13726],{},"│  privates Ticket mit unserem Team zu eröffnen.            │\n",[114,13728,13729],{"class":644,"line":814},[114,13730,13716],{},[114,13732,13733],{"class":644,"line":820},[114,13734,13735],{},"│  [ Dropdown: Kategorie auswählen...              ▼ ]      │\n",[114,13737,13738],{"class":644,"line":826},[114,13739,13740],{},"└───────────────────────────────────────────────────────────┘\n",[29,13742],{},[32,13744,13746],{"id":13745},"_2-ticket-kategorien-berechtigungs-routing","2. Ticket-Kategorien & Berechtigungs-Routing",[22,13748,13749],{},"Du kannst beliebig viele Support-Kategorien anlegen, um Anfragen gezielt an die richtigen Teammitglieder weiterzuleiten:",[40,13751,13752,13794,13806],{},[43,13753,13754,13757],{},[47,13755,13756],{},"Kategorie-Beispiele:",[40,13758,13759,13767,13776,13785],{},[43,13760,13761,13764,13765,261],{},[292,13762,13763],{},"Allgemeiner Support:"," Für Fragen rund um den Server (",[97,13766,7796],{},[43,13768,13769,13772,13773,261],{},[292,13770,13771],{},"Technischer Support:"," Bei Fehlern, Lags oder Bug-Reports (",[97,13774,13775],{},"@Entwickler",[43,13777,13778,13781,13782,261],{},[292,13779,13780],{},"Minecraft-Hilfe:"," Fragen zu In-Game-Accounts, Grundstücken oder Rängen (",[97,13783,13784],{},"@Minecraft-Team",[43,13786,13787,13790,13791,261],{},[292,13788,13789],{},"Bewerbungen & Management:"," Vertrauliche Anfragen (",[97,13792,13793],{},"@Server-Leitung",[43,13795,13796,13799,13800,3008,13803,261],{},[47,13797,13798],{},"Discord-Kategorie (Parent Category):"," Jede Ticket-Art kann in einer eigenen Discord-Kategorie angelegt werden (z. B. ",[97,13801,13802],{},"TICKETS - SUPPORT",[97,13804,13805],{},"TICKETS - TEAM",[43,13807,13808,13811,13812],{},[47,13809,13810],{},"Sichere Berechtigungen:"," Bei der Ticket-Erstellung setzt der Bot automatisch strikte Kanal-Berechtigungen:\n",[40,13813,13814,13820,13823],{},[43,13815,13816,13819],{},[97,13817,13818],{},"@everyone",": Zugriff verweigert (unsichtbar).",[43,13821,13822],{},"Ticket-Ersteller: Lesen, Schreiben, Anhänge hinzufügen.",[43,13824,13825],{},"Kategorie-Support-Rollen: Vollständiger Lese- und Schreibzugriff.",[29,13827],{},[32,13829,13831],{"id":13830},"_3-ticket-workflow-staff-claiming","3. Ticket-Workflow & Staff-Claiming",[22,13833,13834,13835,13838],{},"Sobald ein Nutzer ein Ticket eröffnet, wird ein neuer Kanal (z. B. ",[97,13836,13837],{},"#ticket-0042",") erstellt und das Begrüßungs-Embed gepostet.",[714,13840,13842],{"id":13841},"das-claim-system-staff-zuweisung","Das Claim-System (Staff-Zuweisung):",[40,13844,13845,13852,13855,13862],{},[43,13846,13847,13848,13851],{},"Jedes geöffnete Ticket verfügt über einen ",[47,13849,13850],{},"\"Ticket beanspruchen (Claim)\"","-Button.",[43,13853,13854],{},"Klickt ein Teammitglied auf den Button, wird das Ticket diesem Supporter fest zugewiesen.",[43,13856,13857,13858,13861],{},"Der Kanalname oder das Panel aktualisiert sich (z. B. ",[97,13859,13860],{},"ticket-0042-claim-luca","), und andere Teammitglieder sehen sofort, wer das Ticket aktuell bearbeitet.",[43,13863,13864],{},"Dies verhindert doppelte Antworten und sorgt für klare Verantwortlichkeiten.",[714,13866,13868],{"id":13867},"verfügbare-platzhalter-im-begrüßungs-embed","Verfügbare Platzhalter im Begrüßungs-Embed:",[40,13870,13871,13880,13886,13892],{},[43,13872,13873,13876,13877,261],{},[97,13874,13875],{},"{user}"," – Erwähnt den Ersteller (",[97,13878,13879],{},"@Benutzer",[43,13881,13882,13885],{},[97,13883,13884],{},"{username}"," – Name des Benutzers im Klartext.",[43,13887,13888,13891],{},[97,13889,13890],{},"{server}"," – Name des Discord-Servers.",[43,13893,13894,13897],{},[97,13895,13896],{},"{membercount}"," – Gesamte Mitgliederzahl des Servers.",[29,13899],{},[32,13901,13903],{"id":13902},"_4-transcripts-dokumentation","4. Transcripts & Dokumentation",[22,13905,13906],{},"Nach Abschluss einer Support-Sitzung dokumentiert KiroCloud den gesamten Chatverlauf lückenlos:",[40,13908,13909,13915,13925],{},[43,13910,13911,13914],{},[47,13912,13913],{},"HTML- & Text-Transcripts:"," Alle Nachrichten, Zeitstempel, Avatare, Bilder und hochgeladenen Dateien werden in einem formatierten Transcript archiviert.",[43,13916,13917,13920,13921,13924],{},[47,13918,13919],{},"Log-Kanal:"," Das Transcript wird automatisch als Datei in den konfigurierten Log-Kanal (z. B. ",[97,13922,13923],{},"#ticket-logs",") gesendet.",[43,13926,13927,13930],{},[47,13928,13929],{},"Direktnachricht (DM):"," Der Ticket-Ersteller erhält eine Kopie des Transcripts per DM zur eigenen Dokumentation.",[29,13932],{},[32,13934,13936],{"id":13935},"_5-schließen-auto-close-auto-archive","5. Schließen & Auto-Close \u002F Auto-Archive",[22,13938,13939],{},"Das Schließen von Tickets erfolgt kontrolliert und transparent:",[70,13941,13942,13955,13965],{},[43,13943,13944,13947,13948,13951,13952,50],{},[47,13945,13946],{},"Schließen per Button \u002F Command:"," Nutzer oder Teammitglieder klicken auf ",[47,13949,13950],{},"\"Ticket schließen\""," oder nutzen ",[97,13953,13954],{},"\u002Fticket close",[43,13956,13957,13960,13961,13964],{},[47,13958,13959],{},"Schließungsgrund (Modal):"," Wenn die Option ",[97,13962,13963],{},"require_close_reason"," aktiv ist, muss der Supporter einen kurzen Grund für die Schließung angeben (wird im Transcript und Log vermerkt).",[43,13966,13967,13970],{},[47,13968,13969],{},"Auto-Close bei Inaktivität:"," Reagiert der Ticket-Ersteller über einen definierten Zeitraum (z. B. 24 oder 48 Stunden) nicht mehr auf Rückfragen des Support-Teams, sendet KiroCloud eine Vorwarnung und archiviert\u002Fschließt das Ticket anschließend automatisch.",[29,13972],{},[32,13974,13976],{"id":13975},"_6-feedback-bewertungssystem","6. Feedback & Bewertungssystem",[22,13978,13979],{},"Zur Qualitätssicherung deines Supports bietet KiroCloud ein integriertes Bewertungssystem:",[40,13981,13982,13989,13996],{},[43,13983,13984,13985,13988],{},"Nach dem Schließen eines Tickets erhält der Ersteller eine automatisierte Direktnachricht mit einer ",[47,13986,13987],{},"1-bis-5-Sterne-Bewertung"," und einem optionalen Textfeld für Feedback.",[43,13990,13991,13992,13995],{},"Die abgegebenen Bewertungen werden mit dem Supporter-Namen verknüpft und im internen Team-Feedback-Kanal (",[97,13993,13994],{},"feedbackLogMessageConfig",") protokolliert.",[43,13997,13998],{},"Durchschnittliche Bewertungen der Teammitglieder können im Admin-Dashboard ausgewertet werden.",[944,14000,5465],{},{"title":7,"searchDepth":537,"depth":537,"links":14002},[14003,14006,14007,14011,14012,14013],{"id":13660,"depth":537,"text":13661,"children":14004},[14005],{"id":13667,"depth":763,"text":13668},{"id":13745,"depth":537,"text":13746},{"id":13830,"depth":537,"text":13831,"children":14008},[14009,14010],{"id":13841,"depth":763,"text":13842},{"id":13867,"depth":763,"text":13868},{"id":13902,"depth":537,"text":13903},{"id":13935,"depth":537,"text":13936},{"id":13975,"depth":537,"text":13976},"modules","Professioneller Discord-Support mit Kategorien, Staff-Claiming, HTML-Transcripts und Auto-Close.",{},"\u002Fdocs\u002Fde\u002Fticket-system",{"title":13646,"description":14015},"docs\u002Fde\u002Fticket-system","lNARN-BceEic9NyfzB9cJzJ_HVlirU9tx2A6Qv-UGhQ",{"id":14022,"title":14023,"author":12,"body":14024,"category":958,"description":14443,"extension":549,"lastUpdated":12,"meta":14444,"navigation":551,"order":962,"path":14446,"readTime":12,"seo":14447,"stem":14448,"__hash__":14449},"docs\u002Fdocs\u002Fde\u002Fwebhooks.md","Webhooks",{"type":14,"value":14025,"toc":14434},[14026,14030,14033,14037,14040,14080,14084,14087,14112,14116,14122,14258,14262,14265,14274,14278,14401,14405,14431],[17,14027,14029],{"id":14028},"webhooks-event-streams","Webhooks & Event Streams",[22,14031,14032],{},"Mit Webhooks kannst du externe Systeme (z. B. deinen eigenen Bot-Monitoring-Dienst, Alerting-Tools oder interne Statusseiten) automatisch benachrichtigen lassen, sobald relevante Ereignisse für deine Instanzen in KiroCloud eintreten. Dies ermöglicht dir, auf Events in Echtzeit zu reagieren, ohne die REST-API wiederholt abfragen zu müssen (Polling).",[32,14034,14036],{"id":14035},"_1-webhook-registrieren","1. Webhook registrieren",[22,14038,14039],{},"Webhooks werden direkt in deinem Benutzer-Dashboard konfiguriert:",[70,14041,14042,14048,14053,14059,14065,14074],{},[43,14043,14044,14045,50],{},"Gehe im Dashboard zu ",[47,14046,14047],{},"Einstellungen > Webhooks & Benachrichtigungen",[43,14049,103,14050,50],{},[47,14051,14052],{},"Webhook hinzufügen",[43,14054,14055,14058],{},[47,14056,14057],{},"Name",": Eine eindeutige Bezeichnung (z. B. \"Discord Alerting Service\").",[43,14060,14061,14064],{},[47,14062,14063],{},"Ziel-URL",": Die HTTPS-Adresse deines Servers, an die KiroCloud die POST-Requests senden soll.",[43,14066,14067,14070,14071,261],{},[47,14068,14069],{},"Subscribed Events",": Wähle die Ereignisse aus, über die du benachrichtigt werden möchtest (z. B. ",[97,14072,14073],{},"bot.crashed",[43,14075,14076,14079],{},[47,14077,14078],{},"Signing Secret"," (Empfohlen): Ein geheimer Schlüssel, mit dem KiroCloud die Payload signiert. So validierst du, dass die Anfrage authentisch ist.",[32,14081,14083],{"id":14082},"_2-verfügbare-ereignisse","2. Verfügbare Ereignisse",[22,14085,14086],{},"KiroCloud bietet folgende Event-Typen für deine verwalteten Instanzen:",[40,14088,14089,14094,14100,14106],{},[43,14090,14091,14093],{},[97,14092,14073],{}," - Wird ausgelöst, wenn ein von dir gehosteter Discord-Bot unerwartet beendet wird oder wegen Speichermangels stoppt.",[43,14095,14096,14099],{},[97,14097,14098],{},"bot.started"," - Wird ausgelöst, wenn ein Discord-Bot erfolgreich gestartet wurde.",[43,14101,14102,14105],{},[97,14103,14104],{},"ticket.created"," - Wird ausgelöst, wenn ein neues Support-Ticket zu deinem Account erstellt wird.",[43,14107,14108,14111],{},[97,14109,14110],{},"ticket.updated"," - Wird ausgelöst, wenn ein Support-Ticket beantwortet oder aktualisiert wird.",[32,14113,14115],{"id":14114},"_3-payload-struktur","3. Payload-Struktur",[22,14117,14118,14119,14121],{},"Wenn ein abonniertes Ereignis eintritt, sendet KiroCloud einen HTTP ",[97,14120,11956],{},"-Request an deine Ziel-URL. Der Body ist als JSON-Objekt formatiert:",[635,14123,14125],{"className":7609,"code":14124,"language":7611,"meta":7,"style":7},"{\n  \"event\": \"bot.crashed\",\n  \"timestamp\": \"2026-10-09T00:00:00.000Z\",\n  \"data\": {\n    \"botId\": \"00000000-0000-0000-0000-000000000000\",\n    \"name\": \"MyCommunityBot\",\n    \"exitCode\": 1,\n    \"reason\": \"Process exited with code 1\"\n  }\n}\n",[97,14126,14127,14131,14150,14168,14180,14198,14217,14232,14250,14254],{"__ignoreMap":7},[114,14128,14129],{"class":644,"line":552},[114,14130,1330],{"class":735},[114,14132,14133,14135,14138,14140,14142,14144,14146,14148],{"class":644,"line":537},[114,14134,8430],{"class":735},[114,14136,14137],{"class":1107},"event",[114,14139,742],{"class":735},[114,14141,1170],{"class":735},[114,14143,736],{"class":735},[114,14145,14073],{"class":651},[114,14147,742],{"class":735},[114,14149,1571],{"class":735},[114,14151,14152,14154,14156,14158,14160,14162,14164,14166],{"class":644,"line":763},[114,14153,8430],{"class":735},[114,14155,13127],{"class":1107},[114,14157,742],{"class":735},[114,14159,1170],{"class":735},[114,14161,736],{"class":735},[114,14163,13136],{"class":651},[114,14165,742],{"class":735},[114,14167,1571],{"class":735},[114,14169,14170,14172,14174,14176,14178],{"class":644,"line":802},[114,14171,8430],{"class":735},[114,14173,6550],{"class":1107},[114,14175,742],{"class":735},[114,14177,1170],{"class":735},[114,14179,1161],{"class":735},[114,14181,14182,14184,14186,14188,14190,14192,14194,14196],{"class":644,"line":808},[114,14183,8444],{"class":735},[114,14185,5757],{"class":647},[114,14187,742],{"class":735},[114,14189,1170],{"class":735},[114,14191,736],{"class":735},[114,14193,12820],{"class":651},[114,14195,742],{"class":735},[114,14197,1571],{"class":735},[114,14199,14200,14202,14204,14206,14208,14210,14213,14215],{"class":644,"line":814},[114,14201,8444],{"class":735},[114,14203,8324],{"class":647},[114,14205,742],{"class":735},[114,14207,1170],{"class":735},[114,14209,736],{"class":735},[114,14211,14212],{"class":651},"MyCommunityBot",[114,14214,742],{"class":735},[114,14216,1571],{"class":735},[114,14218,14219,14221,14224,14226,14228,14230],{"class":644,"line":820},[114,14220,8444],{"class":735},[114,14222,14223],{"class":647},"exitCode",[114,14225,742],{"class":735},[114,14227,1170],{"class":735},[114,14229,4956],{"class":1135},[114,14231,1571],{"class":735},[114,14233,14234,14236,14239,14241,14243,14245,14248],{"class":644,"line":826},[114,14235,8444],{"class":735},[114,14237,14238],{"class":647},"reason",[114,14240,742],{"class":735},[114,14242,1170],{"class":735},[114,14244,736],{"class":735},[114,14246,14247],{"class":651},"Process exited with code 1",[114,14249,773],{"class":735},[114,14251,14252],{"class":644,"line":832},[114,14253,817],{"class":735},[114,14255,14256],{"class":644,"line":891},[114,14257,879],{"class":735},[32,14259,14261],{"id":14260},"_4-sicherheit-signaturprüfung-hmac-sha256","4. Sicherheit & Signaturprüfung (HMAC-SHA256)",[22,14263,14264],{},"Um Man-in-the-Middle-Angriffe oder gefälschte Requests zu verhindern, signiert KiroCloud jede Webhook-Anfrage im HTTP-Header:",[635,14266,14268],{"className":10854,"code":14267,"language":10856,"meta":7,"style":7},"X-Kiro-Signature: sha256=a1b2c3d4e5f6...\n",[97,14269,14270],{"__ignoreMap":7},[114,14271,14272],{"class":644,"line":552},[114,14273,14267],{},[714,14275,14277],{"id":14276},"validierungsbeispiel-in-nodejs-express","Validierungsbeispiel in Node.js \u002F Express:",[635,14279,14281],{"className":780,"code":14280,"language":782,"meta":7,"style":7},"import crypto from 'node:crypto';\nimport express from 'express';\n\nconst app = express();\nconst WEBHOOK_SECRET = 'dein_signing_secret';\n\n\u002F\u002F Der rohe Request-Body wird für die Signaturprüfung benötigt\napp.post('\u002Fwebhook', express.json({ verify: (req, res, buf) => { req.rawBody = buf; }}), (req, res) => {\n  const signature = req.headers['x-kiro-signature'];\n  if (!signature) {\n    return res.status(401).send('Missing signature');\n  }\n\n  const hash = crypto.createHmac('sha256', WEBHOOK_SECRET)\n                     .update(req.rawBody)\n                     .digest('hex');\n  const expectedSignature = `sha256=${hash}`;\n\n  if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {\n    console.log('Webhook verifiziert! Event:', req.body.event);\n    res.status(200).send('OK');\n  } else {\n    res.status(401).send('Invalid signature');\n  }\n});\n",[97,14282,14283,14288,14293,14297,14302,14307,14311,14316,14321,14326,14331,14336,14340,14344,14349,14354,14359,14364,14368,14373,14378,14383,14388,14393,14397],{"__ignoreMap":7},[114,14284,14285],{"class":644,"line":552},[114,14286,14287],{},"import crypto from 'node:crypto';\n",[114,14289,14290],{"class":644,"line":537},[114,14291,14292],{},"import express from 'express';\n",[114,14294,14295],{"class":644,"line":763},[114,14296,856],{"emptyLinePlaceholder":551},[114,14298,14299],{"class":644,"line":802},[114,14300,14301],{},"const app = express();\n",[114,14303,14304],{"class":644,"line":808},[114,14305,14306],{},"const WEBHOOK_SECRET = 'dein_signing_secret';\n",[114,14308,14309],{"class":644,"line":814},[114,14310,856],{"emptyLinePlaceholder":551},[114,14312,14313],{"class":644,"line":820},[114,14314,14315],{},"\u002F\u002F Der rohe Request-Body wird für die Signaturprüfung benötigt\n",[114,14317,14318],{"class":644,"line":826},[114,14319,14320],{},"app.post('\u002Fwebhook', express.json({ verify: (req, res, buf) => { req.rawBody = buf; }}), (req, res) => {\n",[114,14322,14323],{"class":644,"line":832},[114,14324,14325],{},"  const signature = req.headers['x-kiro-signature'];\n",[114,14327,14328],{"class":644,"line":891},[114,14329,14330],{},"  if (!signature) {\n",[114,14332,14333],{"class":644,"line":1204},[114,14334,14335],{},"    return res.status(401).send('Missing signature');\n",[114,14337,14338],{"class":644,"line":1209},[114,14339,817],{},[114,14341,14342],{"class":644,"line":1215},[114,14343,856],{"emptyLinePlaceholder":551},[114,14345,14346],{"class":644,"line":1221},[114,14347,14348],{},"  const hash = crypto.createHmac('sha256', WEBHOOK_SECRET)\n",[114,14350,14351],{"class":644,"line":1227},[114,14352,14353],{},"                     .update(req.rawBody)\n",[114,14355,14356],{"class":644,"line":1267},[114,14357,14358],{},"                     .digest('hex');\n",[114,14360,14361],{"class":644,"line":1305},[114,14362,14363],{},"  const expectedSignature = `sha256=${hash}`;\n",[114,14365,14366],{"class":644,"line":1333},[114,14367,856],{"emptyLinePlaceholder":551},[114,14369,14370],{"class":644,"line":1358},[114,14371,14372],{},"  if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {\n",[114,14374,14375],{"class":644,"line":1363},[114,14376,14377],{},"    console.log('Webhook verifiziert! Event:', req.body.event);\n",[114,14379,14380],{"class":644,"line":1368},[114,14381,14382],{},"    res.status(200).send('OK');\n",[114,14384,14385],{"class":644,"line":1374},[114,14386,14387],{},"  } else {\n",[114,14389,14390],{"class":644,"line":1401},[114,14391,14392],{},"    res.status(401).send('Invalid signature');\n",[114,14394,14395],{"class":644,"line":1435},[114,14396,817],{},[114,14398,14399],{"class":644,"line":1440},[114,14400,823],{},[32,14402,14404],{"id":14403},"_5-fehlertoleranz-retry-verhalten","5. Fehlertoleranz & Retry-Verhalten",[40,14406,14407,14417,14424],{},[43,14408,14409,14410,14413,14414,14416],{},"KiroCloud erwartet einen HTTP-Statuscode im Bereich ",[97,14411,14412],{},"2xx"," (z. B. ",[97,14415,12992],{},") innerhalb von 5 Sekunden.",[43,14418,14419,14420,14423],{},"Antwortet dein Endpunkt mit ",[97,14421,14422],{},"5xx"," oder läuft in ein Timeout, unternimmt das System automatische Wiederholungsversuche mit exponentiellem Backoff (bis zu 3 Versuche).",[43,14425,14426,14427,14430],{},"Im Dashboard kannst du über die Schaltfläche ",[47,14428,14429],{},"„Test-Ping senden“"," jederzeit die Erreichbarkeit deines Endpunkts überprüfen.",[944,14432,14433],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":7,"searchDepth":537,"depth":537,"links":14435},[14436,14437,14438,14439,14442],{"id":14035,"depth":537,"text":14036},{"id":14082,"depth":537,"text":14083},{"id":14114,"depth":537,"text":14115},{"id":14260,"depth":537,"text":14261,"children":14440},[14441],{"id":14276,"depth":763,"text":14277},{"id":14403,"depth":537,"text":14404},"Erhalte HTTP-Benachrichtigungen über deine Bot- und Ticket-Ereignisse in Echtzeit",{"icon":14445},"i-lucide-webhook","\u002Fdocs\u002Fde\u002Fwebhooks",{"title":14023,"description":14443},"docs\u002Fde\u002Fwebhooks","7PEWWY6Id8WCOgbfzdREFvwm9qI9wRTdqk2K1ZIfhKY",{"id":14451,"title":969,"author":12,"body":14452,"category":12,"description":14941,"extension":549,"lastUpdated":12,"meta":14942,"navigation":551,"order":962,"path":14943,"readTime":12,"seo":14944,"stem":14948,"__hash__":14949},"docs\u002Fdocs\u002Fde\u002Fwebhooks-vs-rest-websockets.md",{"type":14,"value":14453,"toc":14935},[14454,14458,14472,14475,14477,14481,14487,14489,14493,14496,14578,14585,14587,14591,14594,14608,14863,14865,14869,14872,14932],[17,14455,14457],{"id":14456},"discord-webhooks-vs-rest-vs-websockets-latenz-durchsatz-architektur-guide","Discord Webhooks vs REST vs WebSockets: Latenz, Durchsatz & Architektur-Guide",[22,14459,14460,14461,14463,14464,14467,14468,14471],{},"Entwickler, die Integrationen für Discord bauen, stehen regelmäßig vor der Entscheidung: Sollte eine Funktion über ",[47,14462,14023],{},", die klassische ",[47,14465,14466],{},"REST-API"," oder das persistente ",[47,14469,14470],{},"WebSocket-Gateway"," umgesetzt werden? Jedes Protokoll besitzt völlig unterschiedliche Latenzprofile, CPU-Kosten und Rate-Limit-Restriktionen.",[22,14473,14474],{},"In diesem Architektur-Leitfaden analysieren wir die Messwerte aus unseren Benchmarks und stellen eine praxiserprobte Entscheidungsmatrix vor.",[29,14476],{},[32,14478,14480],{"id":14479},"_1-das-protokoll-spektrum-im-überblick","1. Das Protokoll-Spektrum im Überblick",[635,14482,14485],{"className":14483,"code":14484,"language":1053},[1051],"┌────────────────────────────────────────────────────────────────────────┐\n│                        Discord API Protokolle                          │\n├───────────────────┬────────────────────────────┬───────────────────────┤\n│ Webhooks (HTTP)   │ REST API (HTTP)            │ WebSockets (Gateway)  │\n│ - Unidirektional  │ - Bidirektional (Req\u002FResp) │ - Vollduplex (Events) │\n│ - Token-spezifisch│ - Bot-Token autorisiert    │ - Persistente TCP-Verbindung\n│ - Schneller Post  │ - Vollständiges Datenmodell│ - Sub-Millisekunden Eventing\n└───────────────────┴────────────────────────────┴───────────────────────┘\n",[97,14486,14484],{"__ignoreMap":7},[29,14488],{},[32,14490,14492],{"id":14491},"_2-benchmark-round-trip-latenzen-payload-overheads","2. Benchmark: Round-Trip-Latenzen & Payload-Overheads",[22,14494,14495],{},"Im KiroCloud-Labor haben wir 10.000 Operationen über die drei Protokolle gemessen (Verbindung von unserer deutschen Server-Infrastruktur nach Discord US-East):",[447,14497,14498,14517],{},[450,14499,14500],{},[453,14501,14502,14505,14508,14511,14514],{},[456,14503,14504],{},"Protokoll",[456,14506,14507],{},"Mittlere Latenz (RTT)",[456,14509,14510],{},"TLS Handshake Overhead",[456,14512,14513],{},"Payload Overhead",[456,14515,14516],{},"Eignung",[467,14518,14519,14538,14557],{},[453,14520,14521,14526,14529,14532,14535],{},[472,14522,14523],{},[47,14524,14525],{},"Webhooks (HTTP POST)",[472,14527,14528],{},"~85 ms",[472,14530,14531],{},"Pro Verbindung (sofern kein Keep-Alive)",[472,14533,14534],{},"Gering (reines JSON)",[472,14536,14537],{},"Benachrichtigungen, CI\u002FCD, Logs",[453,14539,14540,14545,14548,14551,14554],{},[472,14541,14542],{},[47,14543,14544],{},"REST API (HTTP)",[472,14546,14547],{},"~92 ms",[472,14549,14550],{},"Pro Verbindung \u002F Connection Pool",[472,14552,14553],{},"Mittel (inkl. Auth-Header)",[472,14555,14556],{},"CRUD-Operationen, Rollen, Kanäle",[453,14558,14559,14564,14569,14572,14575],{},[472,14560,14561],{},[47,14562,14563],{},"WebSocket Gateway",[472,14565,14566],{},[47,14567,14568],{},"\u003C 15 ms",[472,14570,14571],{},"Einmalig beim Start (TCP Session)",[472,14573,14574],{},"Extrem gering (Zlib-Stream)",[472,14576,14577],{},"Interaktionen, Slash Commands, Chat",[109,14579,14580],{},[22,14581,14582,14584],{},[114,14583,2184],{},"\nDas WebSocket-Gateway benötigt nach dem initialen Handshake keinen wiederholten TLS-Aufbau. Ereignisse werden sofort als binäre Frames über die bestehende TCP-Verbindung gestreamt.",[29,14586],{},[32,14588,14590],{"id":14589},"_3-webhooks-der-performante-weg-für-einweg-nachrichten","3. Webhooks: Der performante Weg für Einweg-Nachrichten",[22,14592,14593],{},"Wenn du lediglich Logs (z. B. Server-Starts, Ticket-Benachrichtigungen oder Bann-Meldungen) posten möchtest, ist ein Webhook einem vollständigen Bot-Client haushoch überlegen:",[40,14595,14596,14602],{},[43,14597,14598,14601],{},[47,14599,14600],{},"Kein Bot-Login erforderlich:"," Spart ca. 80–120 MB Node.js Heap-Speicher.",[43,14603,14604,14607],{},[47,14605,14606],{},"Eigene Rate-Limits:"," Webhooks haben separate Rate-Limit-Buckets (typischerweise 5 Requests alle 2 Sekunden pro Webhook), die das globale Bot-Limit nicht belasten.",[635,14609,14611],{"className":1071,"code":14610,"language":1073,"meta":7,"style":7},"export async function sendWebhookLog(webhookUrl: string, content: string, embedData: any) {\n  const response = await fetch(webhookUrl, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application\u002Fjson' },\n    body: JSON.stringify({\n      username: 'KiroCloud Alert Dispatcher',\n      avatar_url: 'https:\u002F\u002Fkirocloud.de\u002Ffavicon.svg',\n      content,\n      embeds: [embedData],\n    }),\n  });\n\n  if (!response.ok) {\n    throw new Error(`Webhook dispatch failed with HTTP ${response.status}`);\n  }\n}\n",[97,14612,14613,14655,14675,14690,14716,14733,14749,14765,14772,14788,14796,14804,14808,14826,14855,14859],{"__ignoreMap":7},[114,14614,14615,14617,14619,14621,14624,14626,14629,14631,14633,14635,14638,14640,14642,14644,14647,14649,14651,14653],{"class":644,"line":552},[114,14616,1152],{"class":1080},[114,14618,4354],{"class":1107},[114,14620,1232],{"class":1107},[114,14622,14623],{"class":1235}," sendWebhookLog",[114,14625,1239],{"class":735},[114,14627,14628],{"class":1242},"webhookUrl",[114,14630,1170],{"class":735},[114,14632,1173],{"class":647},[114,14634,1250],{"class":735},[114,14636,14637],{"class":1242}," content",[114,14639,1170],{"class":735},[114,14641,1173],{"class":647},[114,14643,1250],{"class":735},[114,14645,14646],{"class":1242}," embedData",[114,14648,1170],{"class":735},[114,14650,4898],{"class":647},[114,14652,1300],{"class":735},[114,14654,1161],{"class":735},[114,14656,14657,14659,14661,14663,14665,14667,14669,14671,14673],{"class":644,"line":537},[114,14658,1270],{"class":1107},[114,14660,11304],{"class":745},[114,14662,1276],{"class":735},[114,14664,4383],{"class":1080},[114,14666,11311],{"class":1235},[114,14668,1239],{"class":1166},[114,14670,14628],{"class":745},[114,14672,1250],{"class":735},[114,14674,1161],{"class":735},[114,14676,14677,14680,14682,14684,14686,14688],{"class":644,"line":763},[114,14678,14679],{"class":1166},"    method",[114,14681,1170],{"class":735},[114,14683,1090],{"class":735},[114,14685,11956],{"class":651},[114,14687,1095],{"class":735},[114,14689,1571],{"class":735},[114,14691,14692,14695,14697,14699,14701,14703,14705,14707,14709,14711,14713],{"class":644,"line":802},[114,14693,14694],{"class":1166},"    headers",[114,14696,1170],{"class":735},[114,14698,3035],{"class":735},[114,14700,1090],{"class":735},[114,14702,11257],{"class":1166},[114,14704,1095],{"class":735},[114,14706,1170],{"class":735},[114,14708,1090],{"class":735},[114,14710,11266],{"class":651},[114,14712,1095],{"class":735},[114,14714,14715],{"class":735}," },\n",[114,14717,14718,14721,14723,14725,14727,14729,14731],{"class":644,"line":808},[114,14719,14720],{"class":1166},"    body",[114,14722,1170],{"class":735},[114,14724,6282],{"class":745},[114,14726,50],{"class":735},[114,14728,6287],{"class":1235},[114,14730,1239],{"class":1166},[114,14732,1330],{"class":735},[114,14734,14735,14738,14740,14742,14745,14747],{"class":644,"line":814},[114,14736,14737],{"class":1166},"      username",[114,14739,1170],{"class":735},[114,14741,1090],{"class":735},[114,14743,14744],{"class":651},"KiroCloud Alert Dispatcher",[114,14746,1095],{"class":735},[114,14748,1571],{"class":735},[114,14750,14751,14754,14756,14758,14761,14763],{"class":644,"line":820},[114,14752,14753],{"class":1166},"      avatar_url",[114,14755,1170],{"class":735},[114,14757,1090],{"class":735},[114,14759,14760],{"class":651},"https:\u002F\u002Fkirocloud.de\u002Ffavicon.svg",[114,14762,1095],{"class":735},[114,14764,1571],{"class":735},[114,14766,14767,14770],{"class":644,"line":826},[114,14768,14769],{"class":745},"      content",[114,14771,1571],{"class":735},[114,14773,14774,14777,14779,14781,14784,14786],{"class":644,"line":832},[114,14775,14776],{"class":1166},"      embeds",[114,14778,1170],{"class":735},[114,14780,8377],{"class":1166},[114,14782,14783],{"class":745},"embedData",[114,14785,10279],{"class":1166},[114,14787,1571],{"class":735},[114,14789,14790,14792,14794],{"class":644,"line":891},[114,14791,4886],{"class":735},[114,14793,1300],{"class":1166},[114,14795,1571],{"class":735},[114,14797,14798,14800,14802],{"class":644,"line":1204},[114,14799,2498],{"class":735},[114,14801,1300],{"class":1166},[114,14803,1098],{"class":735},[114,14805,14806],{"class":644,"line":1209},[114,14807,856],{"emptyLinePlaceholder":551},[114,14809,14810,14812,14814,14816,14818,14820,14822,14824],{"class":644,"line":1215},[114,14811,1308],{"class":1080},[114,14813,257],{"class":1166},[114,14815,9622],{"class":735},[114,14817,11398],{"class":745},[114,14819,50],{"class":735},[114,14821,11403],{"class":745},[114,14823,1327],{"class":1166},[114,14825,1330],{"class":735},[114,14827,14828,14830,14832,14834,14836,14838,14841,14843,14845,14847,14849,14851,14853],{"class":644,"line":1221},[114,14829,1336],{"class":1080},[114,14831,1339],{"class":735},[114,14833,1342],{"class":1235},[114,14835,1239],{"class":1166},[114,14837,2651],{"class":735},[114,14839,14840],{"class":651},"Webhook dispatch failed with HTTP ",[114,14842,2657],{"class":735},[114,14844,11398],{"class":745},[114,14846,50],{"class":735},[114,14848,4916],{"class":745},[114,14850,2933],{"class":735},[114,14852,1300],{"class":1166},[114,14854,1098],{"class":735},[114,14856,14857],{"class":644,"line":1227},[114,14858,817],{"class":735},[114,14860,14861],{"class":644,"line":1267},[114,14862,879],{"class":735},[29,14864],{},[32,14866,14868],{"id":14867},"_4-entscheidungsmatrix-für-cloud-entwickler","4. Entscheidungsmatrix für Cloud-Entwickler",[22,14870,14871],{},"Nutze folgende Richtlinie für deine KiroCloud-Applikationen:",[70,14873,14874,14891,14907],{},[43,14875,14876,14879,14880],{},[47,14877,14878],{},"Wähle Webhooks",", wenn du:",[40,14881,14882,14885,14888],{},[43,14883,14884],{},"Git-Commits, GitHub Actions oder CI\u002FCD-Pipelines nach Discord meldest.",[43,14886,14887],{},"Server-Logs und Crash-Berichte von Minecraft- oder FiveM-Servern streamst.",[43,14889,14890],{},"Keine Antworten auf Nachrichten oder Button-Klicks benötigst.",[43,14892,14893,14879,14896],{},[47,14894,14895],{},"Wähle die REST-API",[40,14897,14898,14901,14904],{},[43,14899,14900],{},"Server-Strukturen anlegst (Kanalerstellung, Rollenverwaltung).",[43,14902,14903],{},"Vergangene Chatverläufe nachlädst oder Ticket-Transkripte exportierst.",[43,14905,14906],{},"Interaktive Web-Dashboards baust, die Einstellungen abfragen.",[43,14908,14909,14879,14912],{},[47,14910,14911],{},"Wähle WebSockets (Bot Gateway)",[40,14913,14914,14926,14929],{},[43,14915,14916,14917,381,14920,381,14923,14925],{},"Slash Commands (",[97,14918,14919],{},"\u002Fhelp",[97,14921,14922],{},"\u002Fban",[97,14924,6822],{},") in Echtzeit verarbeitest.",[43,14927,14928],{},"Benutzer-Interaktionen (Buttons, Dropdown-Menüs, Modals) empfängst.",[43,14930,14931],{},"Voice-Kanäle verbindest und Audio streamst.",[944,14933,14934],{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":537,"depth":537,"links":14936},[14937,14938,14939,14940],{"id":14479,"depth":537,"text":14480},{"id":14491,"depth":537,"text":14492},{"id":14589,"depth":537,"text":14590},{"id":14867,"depth":537,"text":14868},"Entwickler, die Integrationen für Discord bauen, stehen regelmäßig vor der Entscheidung: Sollte eine Funktion über Webhooks, die klassische REST-API oder das persistente WebSocket-Gateway umgesetzt werden? Jedes Protokoll besitzt völlig unterschiedliche Latenzprofile, CPU-Kosten und Rate-Limit-Restriktionen.",{},"\u002Fdocs\u002Fde\u002Fwebhooks-vs-rest-websockets",{"title":14945,"description":14941},{"Discord Webhooks vs REST vs WebSockets":14946,"description":14947,"category":6614,"order":552,"author":2000,"readTime":3704,"lastUpdated":2002},"Latenz, Durchsatz & Architektur-Guide","Technischer Vergleich der Discord-Kommunikationsprotokolle. Round-Trip-Latenzen, Payload-Overheads, Rate-Limits und Architektur-Entscheidungsmatrix.","docs\u002Fde\u002Fwebhooks-vs-rest-websockets","4chu8F8OwKvCoxTF-Wgz8VBRywQc8AP4cnnPJ9M5_xQ",{"id":14951,"title":14952,"author":12,"body":14953,"category":958,"description":16258,"extension":549,"lastUpdated":12,"meta":16259,"navigation":551,"order":962,"path":16261,"readTime":12,"seo":16262,"stem":16263,"__hash__":16264},"docs\u002Fdocs\u002Fde\u002Fwebsocket.md","Websocket Events",{"type":14,"value":14954,"toc":16248},[14955,14959,14966,14977,14979,14983,14986,14994,14998,15005,15031,15035,16036,16038,16040,16044,16049,16055,16059,16204,16206,16210,16213,16245],[17,14956,14958],{"id":14957},"websocket-events-telemetrie","WebSocket Events & Telemetrie",[22,14960,14961,14962,14965],{},"Neben den klassischen Webhooks für serverseitige Benachrichtigungen bietet KiroCloud native ",[47,14963,14964],{},"WebSocket","-Verbindungen an. Diese sind ideal, um auf einer Website oder in einem Dashboard Live-Updates (wie CPU-Auslastung oder Konsolenausgaben eines Bots) in Echtzeit darzustellen.",[22,14967,14968,14969,14972,14973,14976],{},"Die WebSocket-API ist direkt unter ",[97,14970,14971],{},"\u002Fws\u002F"," verfügbar. Im Gegensatz zur HTTP-API wird zur Authentifizierung der JWT-Token im Query-String ",[97,14974,14975],{},"?token=..."," oder per Cookie übergeben.",[29,14978],{},[32,14980,14982],{"id":14981},"_1-dashboard-websocket-bot-telemetrie","1. Dashboard WebSocket (Bot-Telemetrie)",[22,14984,14985],{},"Dieser Endpunkt liefert Live-Daten für einen spezifischen Bot. Das ist nützlich, wenn du ein eigenes Web-Interface für deine Discord Bots bauen möchtest, in dem die User die Live-Konsole ihres Bots sehen können.",[22,14987,14988,14991],{},[47,14989,14990],{},"Endpunkt:",[97,14992,14993],{},"wss:\u002F\u002Fapi.kirocloud.de\u002Fws\u002Fdashboard?botId=DEINE_BOT_ID&token=DEIN_API_TOKEN",[714,14995,14997],{"id":14996},"unterstützte-events","Unterstützte Events",[22,14999,15000,15001,15004],{},"Wenn du dich verbindest, erhältst du sofort ein ",[97,15002,15003],{},"subscribed"," Event sowie die Log-Historie (falls vorhanden). Danach pusht der Server bei Änderungen folgende Events:",[40,15006,15007,15013,15019,15025],{},[43,15008,15009,15012],{},[97,15010,15011],{},"bot:status"," - Wird gesendet, wenn der Bot online, offline oder abgestürzt ist.",[43,15014,15015,15018],{},[97,15016,15017],{},"bot:log"," - Jede neue Konsolenausgabe (stdout\u002Fstderr) des Bots.",[43,15020,15021,15024],{},[97,15022,15023],{},"bot:stats"," - Echtzeit CPU- und RAM-Auslastung des Bots (wird i.d.R. im Sekundentakt gepusht).",[43,15026,15027,15030],{},[97,15028,15029],{},"bot:log_history"," - Ein Array der letzten Log-Einträge, direkt nach der Verbindung gesendet.",[714,15032,15034],{"id":15033},"beispiel-implementierung-im-frontend-javascript","Beispiel: Implementierung im Frontend (JavaScript)",[635,15036,15040],{"className":15037,"code":15038,"language":15039,"meta":7,"style":7},"language-html shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!DOCTYPE html>\n\u003Chtml lang=\"de\">\n\u003Chead>\n  \u003Cmeta charset=\"UTF-8\">\n  \u003Ctitle>KiroBot Live Konsole\u003C\u002Ftitle>\n  \u003Cstyle>\n    body { background: #111; color: #0f0; font-family: monospace; padding: 20px; }\n    #console { white-space: pre-wrap; }\n  \u003C\u002Fstyle>\n\u003C\u002Fhead>\n\u003Cbody>\n  \u003Ch2>Live Konsole\u003C\u002Fh2>\n  \u003Cdiv id=\"console\">\u003C\u002Fdiv>\n\n  \u003Cscript>\n    const BOT_ID = '1234567890';\n    \u002F\u002F HINWEIS: Niemals den API-Key dauerhaft im Frontend hardcoden!\n    \u002F\u002F Nutze Cookies oder einen Backend-Proxy in Produktion.\n    const TOKEN = 'DEIN_API_KEY'; \n\n    const ws = new WebSocket(`wss:\u002F\u002Fapi.kirocloud.de\u002Fws\u002Fdashboard?botId=${BOT_ID}&token=${TOKEN}`);\n\n    const consoleDiv = document.getElementById('console');\n\n    ws.onmessage = (event) => {\n      try {\n        const payload = JSON.parse(event.data);\n        \n        switch (payload.event) {\n          case 'subscribed':\n            console.log('Erfolgreich mit dem Websocket verbunden!');\n            break;\n\n          case 'bot:log_history':\n            \u002F\u002F Initialer Log-Dump\n            payload.data.forEach(logLine => {\n              consoleDiv.textContent += logLine + '\\n';\n            });\n            break;\n\n          case 'bot:log':\n            \u002F\u002F Neue, einzelne Log-Zeile\n            consoleDiv.textContent += payload.data + '\\n';\n            window.scrollTo(0, document.body.scrollHeight);\n            break;\n\n          case 'bot:status':\n            consoleDiv.textContent += `[SYSTEM] Bot Status geändert zu: ${payload.data.status}\\n`;\n            break;\n\n          case 'bot:stats':\n            \u002F\u002F payload.data enthält z.B. { cpu: 2.5, memory: 120 }\n            document.title = `RAM: ${payload.data.memory}MB`;\n            break;\n        }\n      } catch (err) {\n        \u002F\u002F Fallback falls die Daten mal kein JSON sind\n        consoleDiv.textContent += event.data + '\\n';\n      }\n    };\n\n    ws.onerror = (error) => {\n      console.error('WebSocket Error:', error);\n      consoleDiv.textContent += `[WS ERROR] Verbindung fehlgeschlagen.\\n`;\n    };\n\n    ws.onclose = () => {\n      consoleDiv.textContent += `[WS CLOSED] Verbindung getrennt.\\n`;\n    };\n  \u003C\u002Fscript>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html",[97,15041,15042,15056,15076,15085,15107,15125,15133,15188,15210,15219,15227,15235,15252,15276,15280,15289,15307,15312,15317,15338,15342,15383,15387,15416,15420,15442,15449,15475,15480,15497,15510,15532,15539,15543,15555,15560,15583,15609,15618,15624,15628,15640,15645,15672,15703,15709,15713,15725,15760,15766,15770,15782,15787,15825,15831,15835,15849,15854,15882,15886,15890,15894,15915,15940,15962,15966,15970,15987,16008,16012,16020,16028],{"__ignoreMap":7},[114,15043,15044,15047,15050,15053],{"class":644,"line":552},[114,15045,15046],{"class":735},"\u003C!",[114,15048,15049],{"class":1166},"DOCTYPE",[114,15051,15052],{"class":1107}," html",[114,15054,15055],{"class":735},">\n",[114,15057,15058,15060,15062,15065,15067,15069,15072,15074],{"class":644,"line":537},[114,15059,3499],{"class":735},[114,15061,15039],{"class":1166},[114,15063,15064],{"class":1107}," lang",[114,15066,1114],{"class":735},[114,15068,742],{"class":735},[114,15070,15071],{"class":651},"de",[114,15073,742],{"class":735},[114,15075,15055],{"class":735},[114,15077,15078,15080,15083],{"class":644,"line":763},[114,15079,3499],{"class":735},[114,15081,15082],{"class":1166},"head",[114,15084,15055],{"class":735},[114,15086,15087,15090,15093,15096,15098,15100,15103,15105],{"class":644,"line":802},[114,15088,15089],{"class":735},"  \u003C",[114,15091,15092],{"class":1166},"meta",[114,15094,15095],{"class":1107}," charset",[114,15097,1114],{"class":735},[114,15099,742],{"class":735},[114,15101,15102],{"class":651},"UTF-8",[114,15104,742],{"class":735},[114,15106,15055],{"class":735},[114,15108,15109,15111,15113,15115,15118,15121,15123],{"class":644,"line":808},[114,15110,15089],{"class":735},[114,15112,13342],{"class":1166},[114,15114,3509],{"class":735},[114,15116,15117],{"class":745},"KiroBot Live Konsole",[114,15119,15120],{"class":735},"\u003C\u002F",[114,15122,13342],{"class":1166},[114,15124,15055],{"class":735},[114,15126,15127,15129,15131],{"class":644,"line":814},[114,15128,15089],{"class":735},[114,15130,944],{"class":1166},[114,15132,15055],{"class":735},[114,15134,15135,15137,15139,15143,15145,15148,15151,15153,15156,15158,15160,15163,15165,15168,15170,15173,15175,15178,15180,15183,15185],{"class":644,"line":820},[114,15136,14720],{"class":647},[114,15138,3035],{"class":735},[114,15140,15142],{"class":15141},"sqsOY"," background",[114,15144,1170],{"class":735},[114,15146,15147],{"class":735}," #",[114,15149,15150],{"class":745},"111",[114,15152,1139],{"class":735},[114,15154,15155],{"class":15141}," color",[114,15157,1170],{"class":735},[114,15159,15147],{"class":735},[114,15161,15162],{"class":745},"0f0",[114,15164,1139],{"class":735},[114,15166,15167],{"class":15141}," font-family",[114,15169,1170],{"class":735},[114,15171,15172],{"class":745}," monospace",[114,15174,1139],{"class":735},[114,15176,15177],{"class":15141}," padding",[114,15179,1170],{"class":735},[114,15181,15182],{"class":1135}," 20px",[114,15184,1139],{"class":735},[114,15186,15187],{"class":735}," }\n",[114,15189,15190,15193,15196,15198,15201,15203,15206,15208],{"class":644,"line":826},[114,15191,15192],{"class":735},"    #",[114,15194,15195],{"class":1135},"console",[114,15197,3035],{"class":735},[114,15199,15200],{"class":15141}," white-space",[114,15202,1170],{"class":735},[114,15204,15205],{"class":745}," pre-wrap",[114,15207,1139],{"class":735},[114,15209,15187],{"class":735},[114,15211,15212,15215,15217],{"class":644,"line":832},[114,15213,15214],{"class":735},"  \u003C\u002F",[114,15216,944],{"class":1166},[114,15218,15055],{"class":735},[114,15220,15221,15223,15225],{"class":644,"line":891},[114,15222,15120],{"class":735},[114,15224,15082],{"class":1166},[114,15226,15055],{"class":735},[114,15228,15229,15231,15233],{"class":644,"line":1204},[114,15230,3499],{"class":735},[114,15232,11368],{"class":1166},[114,15234,15055],{"class":735},[114,15236,15237,15239,15241,15243,15246,15248,15250],{"class":644,"line":1209},[114,15238,15089],{"class":735},[114,15240,32],{"class":1166},[114,15242,3509],{"class":735},[114,15244,15245],{"class":745},"Live Konsole",[114,15247,15120],{"class":735},[114,15249,32],{"class":1166},[114,15251,15055],{"class":735},[114,15253,15254,15256,15259,15261,15263,15265,15267,15269,15272,15274],{"class":644,"line":1215},[114,15255,15089],{"class":735},[114,15257,15258],{"class":1166},"div",[114,15260,11775],{"class":1107},[114,15262,1114],{"class":735},[114,15264,742],{"class":735},[114,15266,15195],{"class":651},[114,15268,742],{"class":735},[114,15270,15271],{"class":735},">\u003C\u002F",[114,15273,15258],{"class":1166},[114,15275,15055],{"class":735},[114,15277,15278],{"class":644,"line":1221},[114,15279,856],{"emptyLinePlaceholder":551},[114,15281,15282,15284,15287],{"class":644,"line":1227},[114,15283,15089],{"class":735},[114,15285,15286],{"class":1166},"script",[114,15288,15055],{"class":735},[114,15290,15291,15293,15296,15298,15300,15303,15305],{"class":644,"line":1267},[114,15292,6505],{"class":1107},[114,15294,15295],{"class":745}," BOT_ID ",[114,15297,1114],{"class":735},[114,15299,1090],{"class":735},[114,15301,15302],{"class":651},"1234567890",[114,15304,1095],{"class":735},[114,15306,1098],{"class":735},[114,15308,15309],{"class":644,"line":1305},[114,15310,15311],{"class":1142},"    \u002F\u002F HINWEIS: Niemals den API-Key dauerhaft im Frontend hardcoden!\n",[114,15313,15314],{"class":644,"line":1333},[114,15315,15316],{"class":1142},"    \u002F\u002F Nutze Cookies oder einen Backend-Proxy in Produktion.\n",[114,15318,15319,15321,15324,15326,15328,15331,15333,15335],{"class":644,"line":1358},[114,15320,6505],{"class":1107},[114,15322,15323],{"class":745}," TOKEN ",[114,15325,1114],{"class":735},[114,15327,1090],{"class":735},[114,15329,15330],{"class":651},"DEIN_API_KEY",[114,15332,1095],{"class":735},[114,15334,1139],{"class":735},[114,15336,15337],{"class":745}," \n",[114,15339,15340],{"class":644,"line":1363},[114,15341,856],{"emptyLinePlaceholder":551},[114,15343,15344,15346,15349,15351,15353,15356,15358,15360,15363,15365,15367,15369,15372,15374,15377,15379,15381],{"class":644,"line":1368},[114,15345,6505],{"class":1107},[114,15347,15348],{"class":745}," ws ",[114,15350,1114],{"class":735},[114,15352,1339],{"class":735},[114,15354,15355],{"class":1235}," WebSocket",[114,15357,1239],{"class":745},[114,15359,2651],{"class":735},[114,15361,15362],{"class":651},"wss:\u002F\u002Fapi.kirocloud.de\u002Fws\u002Fdashboard?botId=",[114,15364,2657],{"class":735},[114,15366,12813],{"class":745},[114,15368,2693],{"class":735},[114,15370,15371],{"class":651},"&token=",[114,15373,2657],{"class":735},[114,15375,15376],{"class":745},"TOKEN",[114,15378,2933],{"class":735},[114,15380,1300],{"class":745},[114,15382,1098],{"class":735},[114,15384,15385],{"class":644,"line":1374},[114,15386,856],{"emptyLinePlaceholder":551},[114,15388,15389,15391,15394,15396,15399,15401,15404,15406,15408,15410,15412,15414],{"class":644,"line":1401},[114,15390,6505],{"class":1107},[114,15392,15393],{"class":745}," consoleDiv ",[114,15395,1114],{"class":735},[114,15397,15398],{"class":745}," document",[114,15400,50],{"class":735},[114,15402,15403],{"class":1235},"getElementById",[114,15405,1239],{"class":745},[114,15407,1095],{"class":735},[114,15409,15195],{"class":651},[114,15411,1095],{"class":735},[114,15413,1300],{"class":745},[114,15415,1098],{"class":735},[114,15417,15418],{"class":644,"line":1435},[114,15419,856],{"emptyLinePlaceholder":551},[114,15421,15422,15425,15427,15430,15432,15434,15436,15438,15440],{"class":644,"line":1440},[114,15423,15424],{"class":745},"    ws",[114,15426,50],{"class":735},[114,15428,15429],{"class":1235},"onmessage",[114,15431,1276],{"class":735},[114,15433,257],{"class":735},[114,15435,14137],{"class":1242},[114,15437,1300],{"class":735},[114,15439,2478],{"class":1107},[114,15441,1161],{"class":735},[114,15443,15444,15447],{"class":644,"line":1483},[114,15445,15446],{"class":1080},"      try",[114,15448,1161],{"class":735},[114,15450,15451,15453,15455,15457,15459,15461,15463,15465,15467,15469,15471,15473],{"class":644,"line":1510},[114,15452,4931],{"class":1107},[114,15454,12182],{"class":745},[114,15456,1276],{"class":735},[114,15458,6282],{"class":745},[114,15460,50],{"class":735},[114,15462,6517],{"class":1235},[114,15464,1239],{"class":1166},[114,15466,14137],{"class":745},[114,15468,50],{"class":735},[114,15470,6550],{"class":745},[114,15472,1300],{"class":1166},[114,15474,1098],{"class":735},[114,15476,15477],{"class":644,"line":1515},[114,15478,15479],{"class":1166},"        \n",[114,15481,15482,15485,15487,15489,15491,15493,15495],{"class":644,"line":1552},[114,15483,15484],{"class":1080},"        switch",[114,15486,257],{"class":1166},[114,15488,12409],{"class":745},[114,15490,50],{"class":735},[114,15492,14137],{"class":745},[114,15494,1327],{"class":1166},[114,15496,1330],{"class":735},[114,15498,15499,15502,15504,15506,15508],{"class":644,"line":1557},[114,15500,15501],{"class":1080},"          case",[114,15503,1090],{"class":735},[114,15505,15003],{"class":651},[114,15507,1095],{"class":735},[114,15509,341],{"class":735},[114,15511,15512,15515,15517,15519,15521,15523,15526,15528,15530],{"class":644,"line":1565},[114,15513,15514],{"class":745},"            console",[114,15516,50],{"class":735},[114,15518,2646],{"class":1235},[114,15520,1239],{"class":1166},[114,15522,1095],{"class":735},[114,15524,15525],{"class":651},"Erfolgreich mit dem Websocket verbunden!",[114,15527,1095],{"class":735},[114,15529,1300],{"class":1166},[114,15531,1098],{"class":735},[114,15533,15534,15537],{"class":644,"line":1574},[114,15535,15536],{"class":1080},"            break",[114,15538,1098],{"class":735},[114,15540,15541],{"class":644,"line":1600},[114,15542,856],{"emptyLinePlaceholder":551},[114,15544,15545,15547,15549,15551,15553],{"class":644,"line":1608},[114,15546,15501],{"class":1080},[114,15548,1090],{"class":735},[114,15550,15029],{"class":651},[114,15552,1095],{"class":735},[114,15554,341],{"class":735},[114,15556,15557],{"class":644,"line":1614},[114,15558,15559],{"class":1142},"            \u002F\u002F Initialer Log-Dump\n",[114,15561,15562,15565,15567,15569,15571,15574,15576,15579,15581],{"class":644,"line":1619},[114,15563,15564],{"class":745},"            payload",[114,15566,50],{"class":735},[114,15568,6550],{"class":745},[114,15570,50],{"class":735},[114,15572,15573],{"class":1235},"forEach",[114,15575,1239],{"class":1166},[114,15577,15578],{"class":1242},"logLine",[114,15580,2478],{"class":1107},[114,15582,1161],{"class":735},[114,15584,15585,15588,15590,15593,15595,15598,15600,15602,15605,15607],{"class":644,"line":1624},[114,15586,15587],{"class":745},"              consoleDiv",[114,15589,50],{"class":735},[114,15591,15592],{"class":745},"textContent",[114,15594,1488],{"class":735},[114,15596,15597],{"class":745}," logLine",[114,15599,4479],{"class":735},[114,15601,1090],{"class":735},[114,15603,15604],{"class":745},"\\n",[114,15606,1095],{"class":735},[114,15608,1098],{"class":735},[114,15610,15611,15614,15616],{"class":644,"line":1629},[114,15612,15613],{"class":735},"            }",[114,15615,1300],{"class":1166},[114,15617,1098],{"class":735},[114,15619,15620,15622],{"class":644,"line":1635},[114,15621,15536],{"class":1080},[114,15623,1098],{"class":735},[114,15625,15626],{"class":644,"line":1640},[114,15627,856],{"emptyLinePlaceholder":551},[114,15629,15630,15632,15634,15636,15638],{"class":644,"line":1673},[114,15631,15501],{"class":1080},[114,15633,1090],{"class":735},[114,15635,15017],{"class":651},[114,15637,1095],{"class":735},[114,15639,341],{"class":735},[114,15641,15642],{"class":644,"line":1704},[114,15643,15644],{"class":1142},"            \u002F\u002F Neue, einzelne Log-Zeile\n",[114,15646,15647,15650,15652,15654,15656,15658,15660,15662,15664,15666,15668,15670],{"class":644,"line":1740},[114,15648,15649],{"class":745},"            consoleDiv",[114,15651,50],{"class":735},[114,15653,15592],{"class":745},[114,15655,1488],{"class":735},[114,15657,12182],{"class":745},[114,15659,50],{"class":735},[114,15661,6550],{"class":745},[114,15663,4479],{"class":735},[114,15665,1090],{"class":735},[114,15667,15604],{"class":745},[114,15669,1095],{"class":735},[114,15671,1098],{"class":735},[114,15673,15674,15677,15679,15682,15684,15686,15688,15690,15692,15694,15696,15699,15701],{"class":644,"line":1775},[114,15675,15676],{"class":745},"            window",[114,15678,50],{"class":735},[114,15680,15681],{"class":1235},"scrollTo",[114,15683,1239],{"class":1166},[114,15685,10775],{"class":1135},[114,15687,1250],{"class":735},[114,15689,15398],{"class":745},[114,15691,50],{"class":735},[114,15693,11368],{"class":745},[114,15695,50],{"class":735},[114,15697,15698],{"class":745},"scrollHeight",[114,15700,1300],{"class":1166},[114,15702,1098],{"class":735},[114,15704,15705,15707],{"class":644,"line":1780},[114,15706,15536],{"class":1080},[114,15708,1098],{"class":735},[114,15710,15711],{"class":644,"line":1813},[114,15712,856],{"emptyLinePlaceholder":551},[114,15714,15715,15717,15719,15721,15723],{"class":644,"line":1832},[114,15716,15501],{"class":1080},[114,15718,1090],{"class":735},[114,15720,15011],{"class":651},[114,15722,1095],{"class":735},[114,15724,341],{"class":735},[114,15726,15727,15729,15731,15733,15735,15737,15740,15742,15744,15746,15748,15750,15752,15754,15756,15758],{"class":644,"line":1837},[114,15728,15649],{"class":745},[114,15730,50],{"class":735},[114,15732,15592],{"class":745},[114,15734,1488],{"class":735},[114,15736,2774],{"class":735},[114,15738,15739],{"class":651},"[SYSTEM] Bot Status geändert zu: ",[114,15741,2657],{"class":735},[114,15743,12409],{"class":745},[114,15745,50],{"class":735},[114,15747,6550],{"class":745},[114,15749,50],{"class":735},[114,15751,4916],{"class":745},[114,15753,2693],{"class":735},[114,15755,15604],{"class":745},[114,15757,2651],{"class":735},[114,15759,1098],{"class":735},[114,15761,15762,15764],{"class":644,"line":1882},[114,15763,15536],{"class":1080},[114,15765,1098],{"class":735},[114,15767,15768],{"class":644,"line":1911},[114,15769,856],{"emptyLinePlaceholder":551},[114,15771,15772,15774,15776,15778,15780],{"class":644,"line":1916},[114,15773,15501],{"class":1080},[114,15775,1090],{"class":735},[114,15777,15023],{"class":651},[114,15779,1095],{"class":735},[114,15781,341],{"class":735},[114,15783,15784],{"class":644,"line":1925},[114,15785,15786],{"class":1142},"            \u002F\u002F payload.data enthält z.B. { cpu: 2.5, memory: 120 }\n",[114,15788,15789,15792,15794,15796,15798,15800,15803,15805,15807,15809,15811,15813,15816,15818,15821,15823],{"class":644,"line":11725},[114,15790,15791],{"class":745},"            document",[114,15793,50],{"class":735},[114,15795,13342],{"class":745},[114,15797,1276],{"class":735},[114,15799,2774],{"class":735},[114,15801,15802],{"class":651},"RAM: ",[114,15804,2657],{"class":735},[114,15806,12409],{"class":745},[114,15808,50],{"class":735},[114,15810,6550],{"class":745},[114,15812,50],{"class":735},[114,15814,15815],{"class":745},"memory",[114,15817,2693],{"class":735},[114,15819,15820],{"class":651},"MB",[114,15822,2651],{"class":735},[114,15824,1098],{"class":735},[114,15826,15827,15829],{"class":644,"line":11731},[114,15828,15536],{"class":1080},[114,15830,1098],{"class":735},[114,15832,15833],{"class":644,"line":11736},[114,15834,12605],{"class":735},[114,15836,15837,15839,15841,15843,15845,15847],{"class":644,"line":11748},[114,15838,5051],{"class":735},[114,15840,4889],{"class":1080},[114,15842,257],{"class":1166},[114,15844,4266],{"class":745},[114,15846,1327],{"class":1166},[114,15848,1330],{"class":735},[114,15850,15851],{"class":644,"line":11824},[114,15852,15853],{"class":1142},"        \u002F\u002F Fallback falls die Daten mal kein JSON sind\n",[114,15855,15856,15859,15861,15863,15865,15868,15870,15872,15874,15876,15878,15880],{"class":644,"line":11829},[114,15857,15858],{"class":745},"        consoleDiv",[114,15860,50],{"class":735},[114,15862,15592],{"class":745},[114,15864,1488],{"class":735},[114,15866,15867],{"class":745}," event",[114,15869,50],{"class":735},[114,15871,6550],{"class":745},[114,15873,4479],{"class":735},[114,15875,1090],{"class":735},[114,15877,15604],{"class":745},[114,15879,1095],{"class":735},[114,15881,1098],{"class":735},[114,15883,15884],{"class":644,"line":11834},[114,15885,5071],{"class":735},[114,15887,15888],{"class":644,"line":11854},[114,15889,4520],{"class":735},[114,15891,15892],{"class":644,"line":11895},[114,15893,856],{"emptyLinePlaceholder":551},[114,15895,15896,15898,15900,15903,15905,15907,15909,15911,15913],{"class":644,"line":11900},[114,15897,15424],{"class":745},[114,15899,50],{"class":735},[114,15901,15902],{"class":1235},"onerror",[114,15904,1276],{"class":735},[114,15906,257],{"class":735},[114,15908,4281],{"class":1242},[114,15910,1300],{"class":735},[114,15912,2478],{"class":1107},[114,15914,1161],{"class":735},[114,15916,15917,15919,15921,15923,15925,15927,15930,15932,15934,15936,15938],{"class":644,"line":11905},[114,15918,9266],{"class":745},[114,15920,50],{"class":735},[114,15922,4281],{"class":1235},[114,15924,1239],{"class":1166},[114,15926,1095],{"class":735},[114,15928,15929],{"class":651},"WebSocket Error:",[114,15931,1095],{"class":735},[114,15933,1250],{"class":735},[114,15935,5064],{"class":745},[114,15937,1300],{"class":1166},[114,15939,1098],{"class":735},[114,15941,15942,15945,15947,15949,15951,15953,15956,15958,15960],{"class":644,"line":11925},[114,15943,15944],{"class":745},"      consoleDiv",[114,15946,50],{"class":735},[114,15948,15592],{"class":745},[114,15950,1488],{"class":735},[114,15952,2774],{"class":735},[114,15954,15955],{"class":651},"[WS ERROR] Verbindung fehlgeschlagen.",[114,15957,15604],{"class":745},[114,15959,2651],{"class":735},[114,15961,1098],{"class":735},[114,15963,15964],{"class":644,"line":11982},[114,15965,4520],{"class":735},[114,15967,15968],{"class":644,"line":11987},[114,15969,856],{"emptyLinePlaceholder":551},[114,15971,15972,15974,15976,15979,15981,15983,15985],{"class":644,"line":11992},[114,15973,15424],{"class":745},[114,15975,50],{"class":735},[114,15977,15978],{"class":1235},"onclose",[114,15980,1276],{"class":735},[114,15982,2906],{"class":735},[114,15984,2478],{"class":1107},[114,15986,1161],{"class":735},[114,15988,15989,15991,15993,15995,15997,15999,16002,16004,16006],{"class":644,"line":12012},[114,15990,15944],{"class":745},[114,15992,50],{"class":735},[114,15994,15592],{"class":745},[114,15996,1488],{"class":735},[114,15998,2774],{"class":735},[114,16000,16001],{"class":651},"[WS CLOSED] Verbindung getrennt.",[114,16003,15604],{"class":745},[114,16005,2651],{"class":735},[114,16007,1098],{"class":735},[114,16009,16010],{"class":644,"line":12068},[114,16011,4520],{"class":735},[114,16013,16014,16016,16018],{"class":644,"line":12073},[114,16015,15214],{"class":735},[114,16017,15286],{"class":1166},[114,16019,15055],{"class":735},[114,16021,16022,16024,16026],{"class":644,"line":12078},[114,16023,15120],{"class":735},[114,16025,11368],{"class":1166},[114,16027,15055],{"class":735},[114,16029,16030,16032,16034],{"class":644,"line":12098},[114,16031,15120],{"class":735},[114,16033,15039],{"class":1166},[114,16035,15055],{"class":735},[29,16037],{},[29,16039],{},[32,16041,16043],{"id":16042},"_2-bot-telemetrie-performance-stream-nodejs-client","2. Bot Telemetrie & Performance Stream (Node.js Client)",[22,16045,16046,16047,50],{},"Für Backend-Dienste, Überwachungstools oder Daemon-Skripte kannst du den WebSocket auch direkt in Node.js konsumieren. Hierfür eignet sich die Standard-Bibliothek ",[97,16048,4508],{},[22,16050,16051,16053],{},[47,16052,14990],{},[97,16054,14993],{},[714,16056,16058],{"id":16057},"implementierung-im-backend-nodejs","Implementierung im Backend (Node.js)",[635,16060,16062],{"className":780,"code":16061,"language":782,"meta":7,"style":7},"\u002F\u002F npm install ws\nimport WebSocket from 'ws';\n\nconst BOT_ID = '00000000-0000-0000-0000-000000000000';\nconst API_TOKEN = 'kiro_sec_DEIN_API_SCHLUESSEL';\nconst ws = new WebSocket(`wss:\u002F\u002Fapi.kirocloud.de\u002Fws\u002Fdashboard?botId=${BOT_ID}&token=${API_TOKEN}`);\n\nws.on('open', () => {\n  console.log('Mit KiroCloud Telemetrie-Stream verbunden!');\n});\n\nws.on('message', (data) => {\n  const payload = JSON.parse(data.toString());\n  \n  if (payload.event === 'subscribed') {\n    console.log('Abonnement für Bot-Telemetrie aktiv.');\n  } else if (payload.event === 'bot:stats') {\n    console.log(`[BOT STATS] CPU: ${payload.data.cpu}% | RAM: ${payload.data.memory}MB`);\n  } else if (payload.event === 'bot:status') {\n    console.log(`[BOT STATUS] Neuer Status: ${payload.data.status}`);\n  }\n});\n\nws.on('close', (code, reason) => {\n  console.log(`Verbindung geschlossen (${code}):`, reason.toString());\n});\n\nws.on('error', (err) => {\n  console.error('WebSocket Fehler:', err.message);\n});\n",[97,16063,16064,16069,16074,16078,16083,16088,16093,16097,16102,16107,16111,16115,16120,16125,16130,16135,16140,16145,16150,16155,16160,16164,16168,16172,16177,16182,16186,16190,16195,16200],{"__ignoreMap":7},[114,16065,16066],{"class":644,"line":552},[114,16067,16068],{},"\u002F\u002F npm install ws\n",[114,16070,16071],{"class":644,"line":537},[114,16072,16073],{},"import WebSocket from 'ws';\n",[114,16075,16076],{"class":644,"line":763},[114,16077,856],{"emptyLinePlaceholder":551},[114,16079,16080],{"class":644,"line":802},[114,16081,16082],{},"const BOT_ID = '00000000-0000-0000-0000-000000000000';\n",[114,16084,16085],{"class":644,"line":808},[114,16086,16087],{},"const API_TOKEN = 'kiro_sec_DEIN_API_SCHLUESSEL';\n",[114,16089,16090],{"class":644,"line":814},[114,16091,16092],{},"const ws = new WebSocket(`wss:\u002F\u002Fapi.kirocloud.de\u002Fws\u002Fdashboard?botId=${BOT_ID}&token=${API_TOKEN}`);\n",[114,16094,16095],{"class":644,"line":820},[114,16096,856],{"emptyLinePlaceholder":551},[114,16098,16099],{"class":644,"line":826},[114,16100,16101],{},"ws.on('open', () => {\n",[114,16103,16104],{"class":644,"line":832},[114,16105,16106],{},"  console.log('Mit KiroCloud Telemetrie-Stream verbunden!');\n",[114,16108,16109],{"class":644,"line":891},[114,16110,823],{},[114,16112,16113],{"class":644,"line":1204},[114,16114,856],{"emptyLinePlaceholder":551},[114,16116,16117],{"class":644,"line":1209},[114,16118,16119],{},"ws.on('message', (data) => {\n",[114,16121,16122],{"class":644,"line":1215},[114,16123,16124],{},"  const payload = JSON.parse(data.toString());\n",[114,16126,16127],{"class":644,"line":1221},[114,16128,16129],{},"  \n",[114,16131,16132],{"class":644,"line":1227},[114,16133,16134],{},"  if (payload.event === 'subscribed') {\n",[114,16136,16137],{"class":644,"line":1267},[114,16138,16139],{},"    console.log('Abonnement für Bot-Telemetrie aktiv.');\n",[114,16141,16142],{"class":644,"line":1305},[114,16143,16144],{},"  } else if (payload.event === 'bot:stats') {\n",[114,16146,16147],{"class":644,"line":1333},[114,16148,16149],{},"    console.log(`[BOT STATS] CPU: ${payload.data.cpu}% | RAM: ${payload.data.memory}MB`);\n",[114,16151,16152],{"class":644,"line":1358},[114,16153,16154],{},"  } else if (payload.event === 'bot:status') {\n",[114,16156,16157],{"class":644,"line":1363},[114,16158,16159],{},"    console.log(`[BOT STATUS] Neuer Status: ${payload.data.status}`);\n",[114,16161,16162],{"class":644,"line":1368},[114,16163,817],{},[114,16165,16166],{"class":644,"line":1374},[114,16167,823],{},[114,16169,16170],{"class":644,"line":1401},[114,16171,856],{"emptyLinePlaceholder":551},[114,16173,16174],{"class":644,"line":1435},[114,16175,16176],{},"ws.on('close', (code, reason) => {\n",[114,16178,16179],{"class":644,"line":1440},[114,16180,16181],{},"  console.log(`Verbindung geschlossen (${code}):`, reason.toString());\n",[114,16183,16184],{"class":644,"line":1483},[114,16185,823],{},[114,16187,16188],{"class":644,"line":1510},[114,16189,856],{"emptyLinePlaceholder":551},[114,16191,16192],{"class":644,"line":1515},[114,16193,16194],{},"ws.on('error', (err) => {\n",[114,16196,16197],{"class":644,"line":1552},[114,16198,16199],{},"  console.error('WebSocket Fehler:', err.message);\n",[114,16201,16202],{"class":644,"line":1557},[114,16203,823],{},[29,16205],{},[32,16207,16209],{"id":16208},"_3-fehlerbehebung-statuscodes","3. Fehlerbehebung & Statuscodes",[22,16211,16212],{},"Sollte die WebSocket-Verbindung sofort nach dem Öffnen wieder getrennt werden, liefert der WebSocket Close Code die Ursache:",[40,16214,16215,16225,16239],{},[43,16216,16217,16220,16221,16224],{},[97,16218,16219],{},"1008 Policy Violation"," mit ",[97,16222,16223],{},"invalid token",": Der übergebene API-Schlüssel ist ungültig, abgelaufen oder hat keinen Zugriff auf die angeforderte Bot-Instanz.",[43,16226,16227,16220,16229,16232,16233,3008,16235,16238],{},[97,16228,16219],{},[97,16230,16231],{},"token+botId required",": Der Pflichtparameter ",[97,16234,5757],{},[97,16236,16237],{},"token"," fehlt in der Verbindungs-URL.",[43,16240,16241,16244],{},[97,16242,16243],{},"1001 Going Away",": Die Bot-Instanz wurde neu gestartet; der Client sollte nach 2 Sekunden eine automatische Wiederverbindung versuchen.",[944,16246,16247],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sqsOY, html code.shiki .sqsOY{--shiki-light:#8796B0;--shiki-default:#B2CCD6;--shiki-dark:#B2CCD6}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":7,"searchDepth":537,"depth":537,"links":16249},[16250,16254,16257],{"id":14981,"depth":537,"text":14982,"children":16251},[16252,16253],{"id":14996,"depth":763,"text":14997},{"id":15033,"depth":763,"text":15034},{"id":16042,"depth":537,"text":16043,"children":16255},[16256],{"id":16057,"depth":763,"text":16058},{"id":16208,"depth":537,"text":16209},"Verbinde dich mit den KiroCloud WebSockets für Echtzeit-Telemetrie und Live-Logs.",{"icon":16260},"i-lucide-radio","\u002Fdocs\u002Fde\u002Fwebsocket",{"title":14952,"description":16258},"docs\u002Fde\u002Fwebsocket","NgWPgRygjzTPay-3tP1LRZCPOBmOaPatYnut4JBJkVY",{"id":16266,"title":969,"author":12,"body":16267,"category":12,"description":17086,"extension":549,"lastUpdated":12,"meta":17087,"navigation":551,"order":962,"path":17088,"readTime":12,"seo":17089,"stem":17093,"__hash__":17094},"docs\u002Fdocs\u002Fde\u002Fzero-downtime-deployments.md",{"type":14,"value":16268,"toc":17079},[16269,16273,16284,16294,16296,16300,16303,16322,16324,16328,16337,16878,16880,16884,16894,16900,16904,16907,17073,17076],[17,16270,16272],{"id":16271},"zero-downtime-bot-deployments-blue-green-sharding-und-graceful-shutdown","Zero-Downtime Bot Deployments: Blue-Green Sharding und Graceful Shutdown",[22,16274,16275,16276,16279,16280,16283],{},"Bei herkömmlichen Bot-Deployments wird der alte Prozess abrupt via ",[97,16277,16278],{},"SIGKILL"," beendet, bevor die neue Version startet. Die Folge für Nutzer: Laufende Interaktionen brechen mit ",[292,16281,16282],{},"\"Die Interaktion ist fehlgeschlagen\""," ab, Voice-Sessions werden getrennt und der Bot ist für 10 bis 30 Sekunden offline.",[22,16285,16286,16287,16220,16290,16293],{},"In großen Produktivumgebungen ist diese Downtime inakzeptabel. In diesem Leitfaden erklären wir, wie du ",[47,16288,16289],{},"unterbrechungsfreie Deployments (Zero-Downtime)",[47,16291,16292],{},"Graceful Shutdown",", Signal-Trapping und Blue-Green Sharding implementierst.",[29,16295],{},[32,16297,16299],{"id":16298},"_1-das-problem-mit-abrupten-neustarts","1. Das Problem mit abrupten Neustarts",[22,16301,16302],{},"Wenn ein Node.js-Prozess unkontrolliert stoppt:",[70,16304,16305,16312,16315],{},[43,16306,16307,16308,16311],{},"Werden offene WebSocket-Frames abgeschnitten, ohne dass Discord den ",[97,16309,16310],{},"Close Frame"," empfängt.",[43,16313,16314],{},"Schlagen asynchrone Datenbank-Transaktionen fehl, was zu inkonsistenten Daten führt.",[43,16316,16317,16318,16321],{},"Müssen nach dem Neustart alle Shards erneut den teuren ",[97,16319,16320],{},"IDENTIFY","-Handshake durchlaufen (Gefahr von Rate-Limits).",[29,16323],{},[32,16325,16327],{"id":16326},"_2-phase-1-graceful-shutdown-mit-sigterm-trapping","2. Phase 1: Graceful Shutdown mit SIGTERM Trapping",[22,16329,16330,16331,186,16333,16336],{},"Ein robuster Bot fängt Betriebssystem-Signale (",[97,16332,13245],{},[97,16334,16335],{},"SIGINT",") ab und leert alle laufenden Aufgaben, bevor er sich beendet:",[635,16338,16340],{"className":1071,"code":16339,"language":1073,"meta":7,"style":7},"import { Client } from 'discord.js';\n\nlet isShuttingDown = false;\n\nexport function registerGracefulShutdown(client: Client, cleanupDb: () => Promise\u003Cvoid>) {\n  const shutdown = async (signal: string) => {\n    if (isShuttingDown) return;\n    isShuttingDown = true;\n\n    console.log(`[Shutdown] Signal ${signal} empfangen. Starte geordneten Shutdown...`);\n\n    \u002F\u002F 1. Status auf 'Wartung' setzen, damit Nutzer Bescheid wissen\n    try {\n      client.user?.setPresence({\n        status: 'dnd',\n        activities: [{ name: 'Aktualisierung läuft...' }],\n      });\n    } catch {}\n\n    \u002F\u002F 2. Keine neuen Slash Commands annehmen (5 Sekunden Schonfrist für laufende Commands)\n    console.log('[Shutdown] Warte 5 Sekunden auf Beendigung laufender Interaktionen...');\n    await new Promise((resolve) => setTimeout(resolve, 5000));\n\n    \u002F\u002F 3. Datenbank-Pools und Redis-Verbindungen sauber schließen\n    console.log('[Shutdown] Schließe Datenbank-Verbindungen...');\n    await cleanupDb();\n\n    \u002F\u002F 4. WebSocket-Verbindung zu Discord ordnungsgemäß abmelden (Code 1000: Normal Closure)\n    console.log('[Shutdown] Trenne Discord Gateway...');\n    client.destroy();\n\n    console.log('[Shutdown] Geordneter Shutdown erfolgreich abgeschlossen.');\n    process.exit(0);\n  };\n\n  process.on('SIGTERM', () => shutdown('SIGTERM'));\n  process.on('SIGINT', () => shutdown('SIGINT'));\n}\n",[97,16341,16342,16362,16366,16379,16383,16423,16449,16465,16476,16480,16510,16514,16519,16525,16543,16559,16587,16595,16604,16608,16613,16634,16667,16671,16676,16697,16707,16711,16716,16737,16750,16754,16775,16793,16797,16801,16838,16874],{"__ignoreMap":7},[114,16343,16344,16346,16348,16350,16352,16354,16356,16358,16360],{"class":644,"line":552},[114,16345,1081],{"class":1080},[114,16347,3035],{"class":735},[114,16349,2443],{"class":745},[114,16351,3050],{"class":735},[114,16353,3053],{"class":1080},[114,16355,1090],{"class":735},[114,16357,2378],{"class":651},[114,16359,1095],{"class":735},[114,16361,1098],{"class":735},[114,16363,16364],{"class":644,"line":537},[114,16365,856],{"emptyLinePlaceholder":551},[114,16367,16368,16370,16373,16375,16377],{"class":644,"line":763},[114,16369,10216],{"class":1107},[114,16371,16372],{"class":745}," isShuttingDown ",[114,16374,1114],{"class":735},[114,16376,10757],{"class":3897},[114,16378,1098],{"class":735},[114,16380,16381],{"class":644,"line":802},[114,16382,856],{"emptyLinePlaceholder":551},[114,16384,16385,16387,16389,16392,16394,16396,16398,16400,16402,16405,16407,16409,16411,16413,16415,16418,16421],{"class":644,"line":808},[114,16386,1152],{"class":1080},[114,16388,1232],{"class":1107},[114,16390,16391],{"class":1235}," registerGracefulShutdown",[114,16393,1239],{"class":735},[114,16395,2438],{"class":1242},[114,16397,1170],{"class":735},[114,16399,2443],{"class":647},[114,16401,1250],{"class":735},[114,16403,16404],{"class":1235}," cleanupDb",[114,16406,1170],{"class":735},[114,16408,2906],{"class":735},[114,16410,2478],{"class":1107},[114,16412,4801],{"class":647},[114,16414,3499],{"class":735},[114,16416,16417],{"class":647},"void",[114,16419,16420],{"class":735},">)",[114,16422,1161],{"class":735},[114,16424,16425,16427,16430,16432,16434,16436,16439,16441,16443,16445,16447],{"class":644,"line":814},[114,16426,1270],{"class":1107},[114,16428,16429],{"class":745}," shutdown",[114,16431,1276],{"class":735},[114,16433,4354],{"class":1107},[114,16435,257],{"class":735},[114,16437,16438],{"class":1242},"signal",[114,16440,1170],{"class":735},[114,16442,1173],{"class":647},[114,16444,1300],{"class":735},[114,16446,2478],{"class":1107},[114,16448,1161],{"class":735},[114,16450,16451,16453,16455,16458,16460,16463],{"class":644,"line":820},[114,16452,9215],{"class":1080},[114,16454,257],{"class":1166},[114,16456,16457],{"class":745},"isShuttingDown",[114,16459,1327],{"class":1166},[114,16461,16462],{"class":1080},"return",[114,16464,1098],{"class":735},[114,16466,16467,16470,16472,16474],{"class":644,"line":826},[114,16468,16469],{"class":745},"    isShuttingDown",[114,16471,1276],{"class":735},[114,16473,3898],{"class":3897},[114,16475,1098],{"class":735},[114,16477,16478],{"class":644,"line":832},[114,16479,856],{"emptyLinePlaceholder":551},[114,16481,16482,16484,16486,16488,16490,16492,16495,16497,16499,16501,16504,16506,16508],{"class":644,"line":891},[114,16483,2915],{"class":745},[114,16485,50],{"class":735},[114,16487,2646],{"class":1235},[114,16489,1239],{"class":1166},[114,16491,2651],{"class":735},[114,16493,16494],{"class":651},"[Shutdown] Signal ",[114,16496,2657],{"class":735},[114,16498,16438],{"class":745},[114,16500,2693],{"class":735},[114,16502,16503],{"class":651}," empfangen. Starte geordneten Shutdown...",[114,16505,2651],{"class":735},[114,16507,1300],{"class":1166},[114,16509,1098],{"class":735},[114,16511,16512],{"class":644,"line":1204},[114,16513,856],{"emptyLinePlaceholder":551},[114,16515,16516],{"class":644,"line":1209},[114,16517,16518],{"class":1142},"    \u002F\u002F 1. Status auf 'Wartung' setzen, damit Nutzer Bescheid wissen\n",[114,16520,16521,16523],{"class":644,"line":1215},[114,16522,4865],{"class":1080},[114,16524,1161],{"class":735},[114,16526,16527,16530,16532,16534,16536,16539,16541],{"class":644,"line":1221},[114,16528,16529],{"class":745},"      client",[114,16531,50],{"class":735},[114,16533,3265],{"class":745},[114,16535,3268],{"class":735},[114,16537,16538],{"class":1235},"setPresence",[114,16540,1239],{"class":1166},[114,16542,1330],{"class":735},[114,16544,16545,16548,16550,16552,16555,16557],{"class":644,"line":1227},[114,16546,16547],{"class":1166},"        status",[114,16549,1170],{"class":735},[114,16551,1090],{"class":735},[114,16553,16554],{"class":651},"dnd",[114,16556,1095],{"class":735},[114,16558,1571],{"class":735},[114,16560,16561,16564,16566,16568,16570,16572,16574,16576,16579,16581,16583,16585],{"class":644,"line":1267},[114,16562,16563],{"class":1166},"        activities",[114,16565,1170],{"class":735},[114,16567,8377],{"class":1166},[114,16569,8369],{"class":735},[114,16571,9686],{"class":1166},[114,16573,1170],{"class":735},[114,16575,1090],{"class":735},[114,16577,16578],{"class":651},"Aktualisierung läuft...",[114,16580,1095],{"class":735},[114,16582,3050],{"class":735},[114,16584,10279],{"class":1166},[114,16586,1571],{"class":735},[114,16588,16589,16591,16593],{"class":644,"line":1305},[114,16590,5051],{"class":735},[114,16592,1300],{"class":1166},[114,16594,1098],{"class":735},[114,16596,16597,16599,16601],{"class":644,"line":1333},[114,16598,4886],{"class":735},[114,16600,4889],{"class":1080},[114,16602,16603],{"class":735}," {}\n",[114,16605,16606],{"class":644,"line":1358},[114,16607,856],{"emptyLinePlaceholder":551},[114,16609,16610],{"class":644,"line":1363},[114,16611,16612],{"class":1142},"    \u002F\u002F 2. Keine neuen Slash Commands annehmen (5 Sekunden Schonfrist für laufende Commands)\n",[114,16614,16615,16617,16619,16621,16623,16625,16628,16630,16632],{"class":644,"line":1368},[114,16616,2915],{"class":745},[114,16618,50],{"class":735},[114,16620,2646],{"class":1235},[114,16622,1239],{"class":1166},[114,16624,1095],{"class":735},[114,16626,16627],{"class":651},"[Shutdown] Warte 5 Sekunden auf Beendigung laufender Interaktionen...",[114,16629,1095],{"class":735},[114,16631,1300],{"class":1166},[114,16633,1098],{"class":735},[114,16635,16636,16638,16640,16642,16644,16646,16648,16650,16652,16654,16656,16658,16660,16663,16665],{"class":644,"line":1374},[114,16637,6535],{"class":1080},[114,16639,1339],{"class":735},[114,16641,4801],{"class":647},[114,16643,1239],{"class":1166},[114,16645,1239],{"class":735},[114,16647,5014],{"class":1242},[114,16649,1300],{"class":735},[114,16651,2478],{"class":1107},[114,16653,5021],{"class":1235},[114,16655,1239],{"class":1166},[114,16657,5014],{"class":745},[114,16659,1250],{"class":735},[114,16661,16662],{"class":1135}," 5000",[114,16664,5036],{"class":1166},[114,16666,1098],{"class":735},[114,16668,16669],{"class":644,"line":1401},[114,16670,856],{"emptyLinePlaceholder":551},[114,16672,16673],{"class":644,"line":1435},[114,16674,16675],{"class":1142},"    \u002F\u002F 3. Datenbank-Pools und Redis-Verbindungen sauber schließen\n",[114,16677,16678,16680,16682,16684,16686,16688,16691,16693,16695],{"class":644,"line":1440},[114,16679,2915],{"class":745},[114,16681,50],{"class":735},[114,16683,2646],{"class":1235},[114,16685,1239],{"class":1166},[114,16687,1095],{"class":735},[114,16689,16690],{"class":651},"[Shutdown] Schließe Datenbank-Verbindungen...",[114,16692,1095],{"class":735},[114,16694,1300],{"class":1166},[114,16696,1098],{"class":735},[114,16698,16699,16701,16703,16705],{"class":644,"line":1483},[114,16700,6535],{"class":1080},[114,16702,16404],{"class":1235},[114,16704,1532],{"class":1166},[114,16706,1098],{"class":735},[114,16708,16709],{"class":644,"line":1510},[114,16710,856],{"emptyLinePlaceholder":551},[114,16712,16713],{"class":644,"line":1515},[114,16714,16715],{"class":1142},"    \u002F\u002F 4. WebSocket-Verbindung zu Discord ordnungsgemäß abmelden (Code 1000: Normal Closure)\n",[114,16717,16718,16720,16722,16724,16726,16728,16731,16733,16735],{"class":644,"line":1552},[114,16719,2915],{"class":745},[114,16721,50],{"class":735},[114,16723,2646],{"class":1235},[114,16725,1239],{"class":1166},[114,16727,1095],{"class":735},[114,16729,16730],{"class":651},"[Shutdown] Trenne Discord Gateway...",[114,16732,1095],{"class":735},[114,16734,1300],{"class":1166},[114,16736,1098],{"class":735},[114,16738,16739,16742,16744,16746,16748],{"class":644,"line":1557},[114,16740,16741],{"class":745},"    client",[114,16743,50],{"class":735},[114,16745,9386],{"class":1235},[114,16747,1532],{"class":1166},[114,16749,1098],{"class":735},[114,16751,16752],{"class":644,"line":1565},[114,16753,856],{"emptyLinePlaceholder":551},[114,16755,16756,16758,16760,16762,16764,16766,16769,16771,16773],{"class":644,"line":1574},[114,16757,2915],{"class":745},[114,16759,50],{"class":735},[114,16761,2646],{"class":1235},[114,16763,1239],{"class":1166},[114,16765,1095],{"class":735},[114,16767,16768],{"class":651},"[Shutdown] Geordneter Shutdown erfolgreich abgeschlossen.",[114,16770,1095],{"class":735},[114,16772,1300],{"class":1166},[114,16774,1098],{"class":735},[114,16776,16777,16780,16782,16785,16787,16789,16791],{"class":644,"line":1600},[114,16778,16779],{"class":745},"    process",[114,16781,50],{"class":735},[114,16783,16784],{"class":1235},"exit",[114,16786,1239],{"class":1166},[114,16788,10775],{"class":1135},[114,16790,1300],{"class":1166},[114,16792,1098],{"class":735},[114,16794,16795],{"class":644,"line":1608},[114,16796,1611],{"class":735},[114,16798,16799],{"class":644,"line":1614},[114,16800,856],{"emptyLinePlaceholder":551},[114,16802,16803,16806,16808,16810,16812,16814,16816,16818,16820,16822,16824,16826,16828,16830,16832,16834,16836],{"class":644,"line":1619},[114,16804,16805],{"class":745},"  process",[114,16807,50],{"class":735},[114,16809,2457],{"class":1235},[114,16811,1239],{"class":1166},[114,16813,1095],{"class":735},[114,16815,13245],{"class":651},[114,16817,1095],{"class":735},[114,16819,1250],{"class":735},[114,16821,2906],{"class":735},[114,16823,2478],{"class":1107},[114,16825,16429],{"class":1235},[114,16827,1239],{"class":1166},[114,16829,1095],{"class":735},[114,16831,13245],{"class":651},[114,16833,1095],{"class":735},[114,16835,5036],{"class":1166},[114,16837,1098],{"class":735},[114,16839,16840,16842,16844,16846,16848,16850,16852,16854,16856,16858,16860,16862,16864,16866,16868,16870,16872],{"class":644,"line":1624},[114,16841,16805],{"class":745},[114,16843,50],{"class":735},[114,16845,2457],{"class":1235},[114,16847,1239],{"class":1166},[114,16849,1095],{"class":735},[114,16851,16335],{"class":651},[114,16853,1095],{"class":735},[114,16855,1250],{"class":735},[114,16857,2906],{"class":735},[114,16859,2478],{"class":1107},[114,16861,16429],{"class":1235},[114,16863,1239],{"class":1166},[114,16865,1095],{"class":735},[114,16867,16335],{"class":651},[114,16869,1095],{"class":735},[114,16871,5036],{"class":1166},[114,16873,1098],{"class":735},[114,16875,16876],{"class":644,"line":1629},[114,16877,879],{"class":735},[29,16879],{},[32,16881,16883],{"id":16882},"_3-phase-2-blue-green-shard-handoff","3. Phase 2: Blue-Green Shard Handoff",[22,16885,16886,16887,16890,16891,1260],{},"Um 0 Sekunden Ausfallzeit zu erreichen, starten wir die neue Version (",[47,16888,16889],{},"Green",") parallel zur alten Version (",[47,16892,16893],{},"Blue",[635,16895,16898],{"className":16896,"code":16897,"language":1053},[1051],"1. Normalbetrieb:\n   Discord Gateway ──► [Cluster Blue v1.0] (Aktiv)\n\n2. Deployment gestartet:\n   [Cluster Green v1.1] startet im Hintergrund, verbindet Shards & lädt Caches.\n\n3. Session-Übergabe:\n   Green signalisiert Betriebsbereitschaft.\n   Blue erhält SIGTERM, vollendet offene Befehle und beendet sich nach 10 Sekunden.\n\n4. Neuer Normalbetrieb:\n   Discord Gateway ──► [Cluster Green v1.1] (Aktiv)\n",[97,16899,16897],{"__ignoreMap":7},[714,16901,16903],{"id":16902},"koordination-über-redis-locks","Koordination über Redis Locks:",[22,16905,16906],{},"Damit nicht zwei Bot-Instanzen gleichzeitig auf denselben Slash Command antworten (Doppel-Ausführung), nutzen wir atomare Redis-Locks:",[635,16908,16910],{"className":1071,"code":16909,"language":1073,"meta":7,"style":7},"import Redis from 'ioredis';\n\nconst redis = new Redis();\n\nexport async function shouldHandleInteraction(interactionId: string): Promise\u003Cboolean> {\n  \u002F\u002F Setze Lock für 10 Sekunden. Nur die erste Instanz erhält 'OK'!\n  const lock = await redis.set(`interaction:${interactionId}`, 'locked', 'EX', 10, 'NX');\n  return lock === 'OK';\n}\n",[97,16911,16912,16928,16932,16948,16952,16985,16990,17053,17069],{"__ignoreMap":7},[114,16913,16914,16916,16918,16920,16922,16924,16926],{"class":644,"line":552},[114,16915,1081],{"class":1080},[114,16917,6114],{"class":745},[114,16919,1087],{"class":1080},[114,16921,1090],{"class":735},[114,16923,6121],{"class":651},[114,16925,1095],{"class":735},[114,16927,1098],{"class":735},[114,16929,16930],{"class":644,"line":537},[114,16931,856],{"emptyLinePlaceholder":551},[114,16933,16934,16936,16938,16940,16942,16944,16946],{"class":644,"line":763},[114,16935,1108],{"class":1107},[114,16937,6136],{"class":745},[114,16939,1114],{"class":735},[114,16941,1339],{"class":735},[114,16943,6143],{"class":1235},[114,16945,1532],{"class":745},[114,16947,1098],{"class":735},[114,16949,16950],{"class":644,"line":802},[114,16951,856],{"emptyLinePlaceholder":551},[114,16953,16954,16956,16958,16960,16963,16965,16968,16970,16972,16974,16976,16978,16981,16983],{"class":644,"line":808},[114,16955,1152],{"class":1080},[114,16957,4354],{"class":1107},[114,16959,1232],{"class":1107},[114,16961,16962],{"class":1235}," shouldHandleInteraction",[114,16964,1239],{"class":735},[114,16966,16967],{"class":1242},"interactionId",[114,16969,1170],{"class":735},[114,16971,1173],{"class":647},[114,16973,1260],{"class":735},[114,16975,4801],{"class":647},[114,16977,3499],{"class":735},[114,16979,16980],{"class":647},"boolean",[114,16982,3509],{"class":735},[114,16984,1161],{"class":735},[114,16986,16987],{"class":644,"line":814},[114,16988,16989],{"class":1142},"  \u002F\u002F Setze Lock für 10 Sekunden. Nur die erste Instanz erhält 'OK'!\n",[114,16991,16992,16994,16997,16999,17001,17003,17005,17007,17009,17011,17014,17016,17018,17020,17022,17024,17027,17029,17031,17033,17035,17037,17039,17041,17043,17045,17047,17049,17051],{"class":644,"line":820},[114,16993,1270],{"class":1107},[114,16995,16996],{"class":745}," lock",[114,16998,1276],{"class":735},[114,17000,4383],{"class":1080},[114,17002,6263],{"class":745},[114,17004,50],{"class":735},[114,17006,3558],{"class":1235},[114,17008,1239],{"class":1166},[114,17010,2651],{"class":735},[114,17012,17013],{"class":651},"interaction:",[114,17015,2657],{"class":735},[114,17017,16967],{"class":745},[114,17019,2933],{"class":735},[114,17021,1250],{"class":735},[114,17023,1090],{"class":735},[114,17025,17026],{"class":651},"locked",[114,17028,1095],{"class":735},[114,17030,1250],{"class":735},[114,17032,1090],{"class":735},[114,17034,10643],{"class":651},[114,17036,1095],{"class":735},[114,17038,1250],{"class":735},[114,17040,10052],{"class":1135},[114,17042,1250],{"class":735},[114,17044,1090],{"class":735},[114,17046,10656],{"class":651},[114,17048,1095],{"class":735},[114,17050,1300],{"class":1166},[114,17052,1098],{"class":735},[114,17054,17055,17057,17059,17061,17063,17065,17067],{"class":644,"line":826},[114,17056,1560],{"class":1080},[114,17058,16996],{"class":745},[114,17060,4919],{"class":735},[114,17062,1090],{"class":735},[114,17064,10682],{"class":651},[114,17066,1095],{"class":735},[114,17068,1098],{"class":735},[114,17070,17071],{"class":644,"line":832},[114,17072,879],{"class":735},[22,17074,17075],{},"Wenn sowohl Blue als auch Green das Event empfangen, antwortet nur die Version, die den Lock erhalten hat – Aktualisierungen erfolgen ohne Verbindungsunterbrechung oder Event-Verlust.",[944,17077,17078],{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":537,"depth":537,"links":17080},[17081,17082,17083],{"id":16298,"depth":537,"text":16299},{"id":16326,"depth":537,"text":16327},{"id":16882,"depth":537,"text":16883,"children":17084},[17085],{"id":16902,"depth":763,"text":16903},"Bei herkömmlichen Bot-Deployments wird der alte Prozess abrupt via SIGKILL beendet, bevor die neue Version startet. Die Folge für Nutzer: Laufende Interaktionen brechen mit \"Die Interaktion ist fehlgeschlagen\" ab, Voice-Sessions werden getrennt und der Bot ist für 10 bis 30 Sekunden offline.",{},"\u002Fdocs\u002Fde\u002Fzero-downtime-deployments",{"title":17090,"description":17086},{"Zero-Downtime Bot Deployments":17091,"description":17092,"category":6614,"order":537,"author":2000,"readTime":2001,"lastUpdated":2002},"Blue-Green Sharding und Graceful Shutdown","Architekturleitfaden für unterbrechungsfreie Discord-Bot-Deployments. Session Handoff, SIGTERM Trapping und Blue-Green Sharding-Strategien.","docs\u002Fde\u002Fzero-downtime-deployments","NHQbxw6GrSJ99kOb3a6k7QV7Amp9Nl_NBDLYgPkKGws",{"id":17096,"title":969,"author":12,"body":17097,"category":12,"description":17105,"extension":549,"lastUpdated":12,"meta":17766,"navigation":551,"order":962,"path":17767,"readTime":12,"seo":17768,"stem":17772,"__hash__":17773},"docs\u002Fdocs\u002Fde\u002Fzero-trust-cloud-bots.md",{"type":14,"value":17098,"toc":17760},[17099,17103,17106,17116,17118,17122,17157,17163,17165,17169,17176,17528,17530,17534,17541,17726,17728,17732,17735,17754,17757],[17,17100,17102],{"id":17101},"zero-trust-architektur-für-cloud-bots-least-privilege-linux-sandbox-isolation","Zero-Trust Architektur für Cloud-Bots: Least-Privilege & Linux-Sandbox-Isolation",[22,17104,17105],{},"Beim Betrieb einer Multi-Tenant Hosting-Plattform wie KiroCloud teilen sich hunderte fremde Bot-Prozesse dieselben physischen Server-Knoten. Wenn ein Benutzer schadhaften Code ausführt (z. B. einen Bot mit Path-Traversal, Krypto-Minern oder Reverse-Shells), darf dieser Prozess unter keinen Umständen auf benachbarte Bots, Systemdateien oder Datenbank-Credentials zugreifen können.",[22,17107,2016,17108,17111,17112,17115],{},[47,17109,17110],{},"Zero-Trust-Sicherheitsmodell"," geht davon aus, dass jeder ausgeführte Prozess potentiell bösartig ist (",[292,17113,17114],{},"\"Never Trust, Always Verify\"","). In diesem Leitfaden erläutern wir die Isolationsebenen moderner Cloud-Bot-Umgebungen.",[29,17117],{},[32,17119,17121],{"id":17120},"_1-die-drei-säulen-der-zero-trust-bot-isolation","1. Die drei Säulen der Zero-Trust Bot-Isolation",[70,17123,17124,17141,17151],{},[43,17125,17126,17129,17130,17133,17134,381,17137,17140],{},[47,17127,17128],{},"Dateisystem-Sandbox (Chroot & Linux Namespaces):"," Jeder Bot sieht ausschließlich sein eigenes Verzeichnis (",[97,17131,17132],{},"\u002Fhome\u002Fkiro\u002Fbots\u002F{botId}","). System-Binaries (",[97,17135,17136],{},"\u002Fbin",[97,17138,17139],{},"\u002Fusr",") werden nur schreibgeschützt (read-only) bereitgestellt.",[43,17142,17143,17146,17147,17150],{},[47,17144,17145],{},"Netzwerk-Segmentierung (Egress Filtering):"," Bots dürfen ausschließlich ausgehende Verbindungen zu den Discord-API-Endpunkten und definierten Datenbank-Ports aufbauen. Der Zugriff auf interne Cloud-Management-Netzwerke (wie ",[97,17148,17149],{},"169.254.169.254"," oder interne Docker-Subnetze) ist auf Kernel-Ebene gesperrt.",[43,17152,17153,17156],{},[47,17154,17155],{},"Flüchtige Zugangsdaten (Ephemeral Tokens):"," Zugriffstoken für Datenbanken und APIs besitzen kurze Lebensdauern (15 bis 60 Minuten) und werden automatisch erneuert.",[635,17158,17161],{"className":17159,"code":17160,"language":1053},[1051],"┌────────────────────────────────────────────────────────────────────────┐\n│                        Physischer Host-Server                          │\n├───────────────────────────────────┬────────────────────────────────────┤\n│  Sandbox A (Bot 1)                │  Sandbox B (Bot 2)                 │\n│  - PID Namespace (isoliert)       │  - PID Namespace (isoliert)        │\n│  - Mount Namespace (Read-Only OS) │  - Mount Namespace (Read-Only OS)  │\n│  - Cgroup RAM Cap: 512 MB         │  - Cgroup RAM Cap: 512 MB          │\n│  - Netfilter: Outbound Whitelist  │  - Netfilter: Outbound Whitelist   │\n└───────────────────────────────────┴────────────────────────────────────┘\n",[97,17162,17160],{"__ignoreMap":7},[29,17164],{},[32,17166,17168],{"id":17167},"_2-linux-namespaces-unprivileged-user-execution","2. Linux Namespaces & Unprivileged User Execution",[22,17170,17171,17172,17175],{},"Ein Bot-Prozess darf unter keinen Umständen als Root oder mit ",[97,17173,17174],{},"sudo","-Rechten ausgeführt werden. Beim Start eines Node.js-Workers wird der Prozess auf einen unprivilegierten System-Benutzer herabgestuft:",[635,17177,17179],{"className":1071,"code":17178,"language":1073,"meta":7,"style":7},"import { spawn } from 'node:child_process';\n\nexport function spawnSandboxedBot(botId: string, botEntrypoint: string) {\n  const botDir = `\u002Fvar\u002Fkiro\u002Fbots\u002F${botId}`;\n\n  const child = spawn('node', [botEntrypoint], {\n    cwd: botDir,\n    uid: 1005, \u002F\u002F Unprivilegierter System-Nutzer 'kiro-runner'\n    gid: 1005,\n    env: {\n      NODE_ENV: 'production',\n      PATH: '\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin',\n      BOT_ID: botId,\n    },\n    \u002F\u002F Trennung von Standard-Ein- und Ausgabe\n    stdio: ['ignore', 'pipe', 'pipe'],\n  });\n\n  child.stdout.on('data', (chunk) => {\n    \u002F\u002F Weiterleitung in den KiroCloud WebSocket Live-Log-Stream\n    broadcastBotLog(botId, chunk.toString());\n  });\n\n  return child;\n}\n",[97,17180,17181,17202,17206,17236,17258,17262,17294,17305,17320,17331,17340,17356,17372,17384,17388,17393,17429,17437,17441,17476,17481,17504,17512,17516,17524],{"__ignoreMap":7},[114,17182,17183,17185,17187,17190,17192,17194,17196,17198,17200],{"class":644,"line":552},[114,17184,1081],{"class":1080},[114,17186,3035],{"class":735},[114,17188,17189],{"class":745}," spawn",[114,17191,3050],{"class":735},[114,17193,3053],{"class":1080},[114,17195,1090],{"class":735},[114,17197,5735],{"class":651},[114,17199,1095],{"class":735},[114,17201,1098],{"class":735},[114,17203,17204],{"class":644,"line":537},[114,17205,856],{"emptyLinePlaceholder":551},[114,17207,17208,17210,17212,17215,17217,17219,17221,17223,17225,17228,17230,17232,17234],{"class":644,"line":763},[114,17209,1152],{"class":1080},[114,17211,1232],{"class":1107},[114,17213,17214],{"class":1235}," spawnSandboxedBot",[114,17216,1239],{"class":735},[114,17218,5757],{"class":1242},[114,17220,1170],{"class":735},[114,17222,1173],{"class":647},[114,17224,1250],{"class":735},[114,17226,17227],{"class":1242}," botEntrypoint",[114,17229,1170],{"class":735},[114,17231,1173],{"class":647},[114,17233,1300],{"class":735},[114,17235,1161],{"class":735},[114,17237,17238,17240,17243,17245,17247,17250,17252,17254,17256],{"class":644,"line":802},[114,17239,1270],{"class":1107},[114,17241,17242],{"class":745}," botDir",[114,17244,1276],{"class":735},[114,17246,2774],{"class":735},[114,17248,17249],{"class":651},"\u002Fvar\u002Fkiro\u002Fbots\u002F",[114,17251,2657],{"class":735},[114,17253,5757],{"class":745},[114,17255,2933],{"class":735},[114,17257,1098],{"class":735},[114,17259,17260],{"class":644,"line":808},[114,17261,856],{"emptyLinePlaceholder":551},[114,17263,17264,17266,17269,17271,17273,17275,17277,17279,17281,17283,17285,17288,17290,17292],{"class":644,"line":814},[114,17265,1270],{"class":1107},[114,17267,17268],{"class":745}," child",[114,17270,1276],{"class":735},[114,17272,17189],{"class":1235},[114,17274,1239],{"class":1166},[114,17276,1095],{"class":735},[114,17278,5915],{"class":651},[114,17280,1095],{"class":735},[114,17282,1250],{"class":735},[114,17284,8377],{"class":1166},[114,17286,17287],{"class":745},"botEntrypoint",[114,17289,10279],{"class":1166},[114,17291,1250],{"class":735},[114,17293,1161],{"class":735},[114,17295,17296,17299,17301,17303],{"class":644,"line":820},[114,17297,17298],{"class":1166},"    cwd",[114,17300,1170],{"class":735},[114,17302,17242],{"class":745},[114,17304,1571],{"class":735},[114,17306,17307,17310,17312,17315,17317],{"class":644,"line":826},[114,17308,17309],{"class":1166},"    uid",[114,17311,1170],{"class":735},[114,17313,17314],{"class":1135}," 1005",[114,17316,1250],{"class":735},[114,17318,17319],{"class":1142}," \u002F\u002F Unprivilegierter System-Nutzer 'kiro-runner'\n",[114,17321,17322,17325,17327,17329],{"class":644,"line":832},[114,17323,17324],{"class":1166},"    gid",[114,17326,1170],{"class":735},[114,17328,17314],{"class":1135},[114,17330,1571],{"class":735},[114,17332,17333,17336,17338],{"class":644,"line":891},[114,17334,17335],{"class":1166},"    env",[114,17337,1170],{"class":735},[114,17339,1161],{"class":735},[114,17341,17342,17345,17347,17349,17352,17354],{"class":644,"line":1204},[114,17343,17344],{"class":1166},"      NODE_ENV",[114,17346,1170],{"class":735},[114,17348,1090],{"class":735},[114,17350,17351],{"class":651},"production",[114,17353,1095],{"class":735},[114,17355,1571],{"class":735},[114,17357,17358,17361,17363,17365,17368,17370],{"class":644,"line":1209},[114,17359,17360],{"class":1166},"      PATH",[114,17362,1170],{"class":735},[114,17364,1090],{"class":735},[114,17366,17367],{"class":651},"\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin",[114,17369,1095],{"class":735},[114,17371,1571],{"class":735},[114,17373,17374,17377,17379,17382],{"class":644,"line":1215},[114,17375,17376],{"class":1166},"      BOT_ID",[114,17378,1170],{"class":735},[114,17380,17381],{"class":745}," botId",[114,17383,1571],{"class":735},[114,17385,17386],{"class":644,"line":1221},[114,17387,3278],{"class":735},[114,17389,17390],{"class":644,"line":1227},[114,17391,17392],{"class":1142},"    \u002F\u002F Trennung von Standard-Ein- und Ausgabe\n",[114,17394,17395,17398,17400,17402,17404,17407,17409,17411,17413,17415,17417,17419,17421,17423,17425,17427],{"class":644,"line":1267},[114,17396,17397],{"class":1166},"    stdio",[114,17399,1170],{"class":735},[114,17401,8377],{"class":1166},[114,17403,1095],{"class":735},[114,17405,17406],{"class":651},"ignore",[114,17408,1095],{"class":735},[114,17410,1250],{"class":735},[114,17412,1090],{"class":735},[114,17414,2870],{"class":651},[114,17416,1095],{"class":735},[114,17418,1250],{"class":735},[114,17420,1090],{"class":735},[114,17422,2870],{"class":651},[114,17424,1095],{"class":735},[114,17426,10279],{"class":1166},[114,17428,1571],{"class":735},[114,17430,17431,17433,17435],{"class":644,"line":1305},[114,17432,2498],{"class":735},[114,17434,1300],{"class":1166},[114,17436,1098],{"class":735},[114,17438,17439],{"class":644,"line":1333},[114,17440,856],{"emptyLinePlaceholder":551},[114,17442,17443,17446,17448,17451,17453,17455,17457,17459,17461,17463,17465,17467,17470,17472,17474],{"class":644,"line":1358},[114,17444,17445],{"class":745},"  child",[114,17447,50],{"class":735},[114,17449,17450],{"class":745},"stdout",[114,17452,50],{"class":735},[114,17454,2457],{"class":1235},[114,17456,1239],{"class":1166},[114,17458,1095],{"class":735},[114,17460,6550],{"class":651},[114,17462,1095],{"class":735},[114,17464,1250],{"class":735},[114,17466,257],{"class":735},[114,17468,17469],{"class":1242},"chunk",[114,17471,1300],{"class":735},[114,17473,2478],{"class":1107},[114,17475,1161],{"class":735},[114,17477,17478],{"class":644,"line":1363},[114,17479,17480],{"class":1142},"    \u002F\u002F Weiterleitung in den KiroCloud WebSocket Live-Log-Stream\n",[114,17482,17483,17486,17488,17490,17492,17495,17497,17499,17502],{"class":644,"line":1368},[114,17484,17485],{"class":1235},"    broadcastBotLog",[114,17487,1239],{"class":1166},[114,17489,5757],{"class":745},[114,17491,1250],{"class":735},[114,17493,17494],{"class":745}," chunk",[114,17496,50],{"class":735},[114,17498,1537],{"class":1235},[114,17500,17501],{"class":1166},"())",[114,17503,1098],{"class":735},[114,17505,17506,17508,17510],{"class":644,"line":1374},[114,17507,2498],{"class":735},[114,17509,1300],{"class":1166},[114,17511,1098],{"class":735},[114,17513,17514],{"class":644,"line":1401},[114,17515,856],{"emptyLinePlaceholder":551},[114,17517,17518,17520,17522],{"class":644,"line":1435},[114,17519,1560],{"class":1080},[114,17521,17268],{"class":745},[114,17523,1098],{"class":735},[114,17525,17526],{"class":644,"line":1440},[114,17527,879],{"class":735},[29,17529],{},[32,17531,17533],{"id":17532},"_3-schutz-vor-path-traversal-in-dateimanagern","3. Schutz vor Path-Traversal in Dateimanagern",[22,17535,17536,17537,17540],{},"Wenn Nutzer Dateien über das Web-Dashboard hochladen oder editieren, muss jeder Pfad gegen Directory-Traversal-Angriffe (",[97,17538,17539],{},"..\u002F..\u002Fetc\u002Fpasswd",") verifiziert werden:",[635,17542,17544],{"className":1071,"code":17543,"language":1073,"meta":7,"style":7},"import path from 'node:path';\n\nexport function resolveSafeBotPath(baseBotDir: string, userPath: string): string {\n  \u002F\u002F Normalisierung und Auflösung des absoluten Pfads\n  const resolved = path.resolve(baseBotDir, userPath);\n\n  \u002F\u002F Verifikation, dass der Pfad strikt innerhalb des Bot-Verzeichnisses liegt\n  if (!resolved.startsWith(baseBotDir + path.sep) && resolved !== baseBotDir) {\n    throw new Error('Sicherheitsverletzung: Zugriff außerhalb des Bot-Verzeichnisses verweigert (Path Traversal erkannt).');\n  }\n\n  return resolved;\n}\n",[97,17545,17546,17562,17566,17599,17604,17631,17635,17640,17685,17706,17710,17714,17722],{"__ignoreMap":7},[114,17547,17548,17550,17552,17554,17556,17558,17560],{"class":644,"line":552},[114,17549,1081],{"class":1080},[114,17551,2567],{"class":745},[114,17553,1087],{"class":1080},[114,17555,1090],{"class":735},[114,17557,2574],{"class":651},[114,17559,1095],{"class":735},[114,17561,1098],{"class":735},[114,17563,17564],{"class":644,"line":537},[114,17565,856],{"emptyLinePlaceholder":551},[114,17567,17568,17570,17572,17575,17577,17580,17582,17584,17586,17589,17591,17593,17595,17597],{"class":644,"line":763},[114,17569,1152],{"class":1080},[114,17571,1232],{"class":1107},[114,17573,17574],{"class":1235}," resolveSafeBotPath",[114,17576,1239],{"class":735},[114,17578,17579],{"class":1242},"baseBotDir",[114,17581,1170],{"class":735},[114,17583,1173],{"class":647},[114,17585,1250],{"class":735},[114,17587,17588],{"class":1242}," userPath",[114,17590,1170],{"class":735},[114,17592,1173],{"class":647},[114,17594,1260],{"class":735},[114,17596,1173],{"class":647},[114,17598,1161],{"class":735},[114,17600,17601],{"class":644,"line":802},[114,17602,17603],{"class":1142},"  \u002F\u002F Normalisierung und Auflösung des absoluten Pfads\n",[114,17605,17606,17608,17611,17613,17615,17617,17619,17621,17623,17625,17627,17629],{"class":644,"line":808},[114,17607,1270],{"class":1107},[114,17609,17610],{"class":745}," resolved",[114,17612,1276],{"class":735},[114,17614,2752],{"class":745},[114,17616,50],{"class":735},[114,17618,5014],{"class":1235},[114,17620,1239],{"class":1166},[114,17622,17579],{"class":745},[114,17624,1250],{"class":735},[114,17626,17588],{"class":745},[114,17628,1300],{"class":1166},[114,17630,1098],{"class":735},[114,17632,17633],{"class":644,"line":814},[114,17634,856],{"emptyLinePlaceholder":551},[114,17636,17637],{"class":644,"line":820},[114,17638,17639],{"class":1142},"  \u002F\u002F Verifikation, dass der Pfad strikt innerhalb des Bot-Verzeichnisses liegt\n",[114,17641,17642,17644,17646,17648,17651,17653,17656,17658,17660,17662,17664,17666,17669,17671,17674,17676,17678,17681,17683],{"class":644,"line":826},[114,17643,1308],{"class":1080},[114,17645,257],{"class":1166},[114,17647,9622],{"class":735},[114,17649,17650],{"class":745},"resolved",[114,17652,50],{"class":735},[114,17654,17655],{"class":1235},"startsWith",[114,17657,1239],{"class":1166},[114,17659,17579],{"class":745},[114,17661,4479],{"class":735},[114,17663,2752],{"class":745},[114,17665,50],{"class":735},[114,17667,17668],{"class":745},"sep",[114,17670,1327],{"class":1166},[114,17672,17673],{"class":735},"&&",[114,17675,17610],{"class":745},[114,17677,1321],{"class":735},[114,17679,17680],{"class":745}," baseBotDir",[114,17682,1327],{"class":1166},[114,17684,1330],{"class":735},[114,17686,17687,17689,17691,17693,17695,17697,17700,17702,17704],{"class":644,"line":832},[114,17688,1336],{"class":1080},[114,17690,1339],{"class":735},[114,17692,1342],{"class":1235},[114,17694,1239],{"class":1166},[114,17696,1095],{"class":735},[114,17698,17699],{"class":651},"Sicherheitsverletzung: Zugriff außerhalb des Bot-Verzeichnisses verweigert (Path Traversal erkannt).",[114,17701,1095],{"class":735},[114,17703,1300],{"class":1166},[114,17705,1098],{"class":735},[114,17707,17708],{"class":644,"line":891},[114,17709,817],{"class":735},[114,17711,17712],{"class":644,"line":1204},[114,17713,856],{"emptyLinePlaceholder":551},[114,17715,17716,17718,17720],{"class":644,"line":1209},[114,17717,1560],{"class":1080},[114,17719,17610],{"class":745},[114,17721,1098],{"class":735},[114,17723,17724],{"class":644,"line":1215},[114,17725,879],{"class":735},[29,17727],{},[32,17729,17731],{"id":17730},"_4-least-privilege-datenbankzugriff","4. Least-Privilege Datenbankzugriff",[22,17733,17734],{},"Wenn ein Bot mit einer SQL-Datenbank interagiert, sollte niemals der PostgreSQL-Superuser verwendet werden:",[40,17736,17737,17740,17747],{},[43,17738,17739],{},"Eigene Datenbank und eigener Datenbanknutzer pro Bot",[43,17741,17742,17743,17746],{},"Keine Rechte für ",[97,17744,17745],{},"DROP DATABASE"," oder Manipulation von Systemtabellen",[43,17748,17749,17750,17753],{},"Maximale Verbindungslimits pro Bot (z. B. ",[97,17751,17752],{},"max_connections = 10","), um Denial-of-Service auf dem Datenbank-Server zu verhindern",[22,17755,17756],{},"Auf KiroCloud sorgt diese Architektur dafür, dass jeder Bot in einer vollständig isolierten Sandbox läuft – für maximale Stabilität und Sicherheit aller gehosteten Kunden-Instanzen.",[944,17758,17759],{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":537,"depth":537,"links":17761},[17762,17763,17764,17765],{"id":17120,"depth":537,"text":17121},{"id":17167,"depth":537,"text":17168},{"id":17532,"depth":537,"text":17533},{"id":17730,"depth":537,"text":17731},{},"\u002Fdocs\u002Fde\u002Fzero-trust-cloud-bots",{"title":17769,"description":17105},{"Zero-Trust Architektur für Cloud-Bots":17770,"description":17771,"category":1999,"order":763,"author":2000,"readTime":3704,"lastUpdated":2002},"Least-Privilege & Linux-Sandbox-Isolation","Umfassender Leitfaden zum Aufbau von Zero-Trust Multi-Tenant Hostings für Discord Bots. Linux Namespaces, Cgroups, Ephemeral Tokens und Outbound-Filter.","docs\u002Fde\u002Fzero-trust-cloud-bots","JGyFQiJqJ7OA0jHML-cmBlPL1fKZeGoeC4AiLCJDBs8",{"enabled":551,"clientPubId":17775,"docsSlotId":7,"newsSlotId":7,"guidesSlotId":7,"dashboardSlotId":7,"docsEnabled":551,"newsEnabled":551,"guidesEnabled":551,"dashboardEnabled":551},"ca-pub-9454065621077312"]