Ausführungssemantik, Einschränkungen und Sicherheit

Diese Seite fasst zusammen, wie sich ein Script zur Laufzeit verhält (Reihenfolge, Transaktionen, Fehler, Sperren), welchen statischen Einschränkungen es bei der Speicherung unterliegt und sein Sicherheitsmodell. Zur Syntax siehe den Statement-Katalog und die Wertausdrücke; für praktische Kombinationen siehe das Cookbook.

Ausführungsreihenfolge

  • statements werden von oben nach unten sequenziell ausgeführt. Sobald die Ausführung ein Return erreicht, endet sie an diesem Punkt.
  • Die Ausführung erfolgt inline auf dem Pfad, der die Aufrufanfrage verarbeitet. Die Antwort des Aufrufs ist unmittelbar das Ausführungsergebnis (zur Form der Antwort siehe Anfrage und Antwort in der Script-Übersicht), und die Zeit für eine einzelne Ausführung wird unten unter Zeitbudget behandelt.

Ausführungssemantik

Guard (Vorbedingungen)

Es gibt kein dediziertes Guard-Statement. Man drückt es mit If und then:[Return] aus. Bei einer Verletzung der Bedingung wird ein Ergebnis zurückgegeben und die nachfolgenden Statements werden nicht ausgeführt (ein Script ohne Guard ist selbstverständlich ebenfalls möglich).

{ "type": "If", "condition": { "<": [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] },
  "then": [ { "type": "Return", "value": { "ok": false, "reason": "insufficient credit" }, "statusCode": 402 } ] }

Keine Transaktionen und Best-Effort-Kompensation

Ein Script ist keine Transaktion. Bei einem Fehler versucht die Engine, die bisher ausgeführten Vorgänge zu kompensieren (Kompensation), und gibt die Fehlerursache zurück, jedoch mit den folgenden Einschränkungen (als Designkompromiss in Kauf genommen).

  • Das Rückgängigmachen einer Löschung erzeugt eine neue sys.id, wodurch Referenzen, die darauf zeigten, brechen.
  • Externe Effekte (Http) sind irreversibel (ein bereits abgesetzter Aufruf und dessen Kosten lassen sich nicht rückgängig machen).
  • Wenn die Kompensation gar nicht ausgeführt wird, kann ein nicht kompensierter Zustand zurückbleiben.

Wenn Sie echte Atomarität benötigen, kompensieren Sie im Script selbst oder platzieren Sie nicht rückgängig zu machende Vorgänge (etwa externe Aufrufe) ganz am Ende. Am gefährlichsten ist die Reihenfolge, die "sich durchkettet, aber nicht zurückrollen lässt und dennoch sicher aussieht".

Optimistisches Sperren

Update-/Patch-Konkurrenz grenzen Sie über das version-Feld von ResourceUpdate und ResourcePatch ein. Geben Sie version (ein Wertausdruck, Int) an, wird nur dann aktualisiert, wenn es mit der aktuellen sys.version des Ziels übereinstimmt; bei Nichtübereinstimmung wird mit einem Versionskonfliktfehler abgebrochen (lokal mit Try/catch behandelbar). Lassen Sie es weg, gilt last-write-wins ohne Prüfung. Üblicherweise liest man zuerst mit ResourceRead oder ResourceFind und übergibt diese sys.version (siehe Optimistisches Sperren mit CAS im Cookbook).

Schreibvorgänge gehen an origin

Schreibvorgänge landen immer in origin (draft), und die Sichtbarkeit auf der Auslieferung (CDA/ACDA) wird über publish gesteuert (das publish von ResourceCreate/ResourceUpdate/ResourcePatch oder ResourcePublish/ResourceUnpublish).

Was als Fehler zählt

Schlägt während der Ausführung ein Statement fehl, wird die Ausführung an dieser Stelle abgebrochen, sofern kein Try diesen Fehler behandelt. Die Engine versucht dabei, die bis dahin ausgeführten Vorgänge rückgängig zu machen. Das Rückgängigmachen hat Grenzen; Einzelheiten behandelt Keine Transaktionen und Best-Effort-Kompensation.

Steht das fehlgeschlagene Statement in einem Try, können Sie diesen Fehler im catch behandeln. Innerhalb des catch referenzieren Sie den Inhalt des Fehlers ({ message }) über /error. Welches Statement fehlgeschlagen ist, steht nicht darin.

Die folgenden Fälle werden als Fehler behandelt.

Return ist kein Fehler. Es beendet die Ausführung regulär vorzeitig und geht daher nicht an catch über.

Zwei Arten, wie Http fehlschlägt

Ein Fehlschlag von Http fällt in eine von zwei Arten, je nachdem, ob er als status-Antwort behandelt wird. Von diesem Unterschied hängt ab, ob retry und ignoreStatusCode greifen.

MerkmalAls status-Antwort behandeltSofortiger Fehlschlag
Betroffene FälleDie Ziel-API antwortet mit einem status von 400 oder höher; eine Zeitüberschreitung (status 504); keine Verbindung zur Ziel-API oder die Antwort konnte nicht gelesen werden (status 502); der Antwort-Body überschreitet 10MiB (status 502)responseType ist "Json", aber der Body einer erfolgreichen Antwort ist kein JSON; die zu sendende Datei überschreitet das Download-Limit; die Datei-URL antwortet mit einem status außerhalb von 2xx oder ist nicht erreichbar; der Wert eines part hat ein ungültiges Format
retryWird so oft wiederholt wie angegebenWird nicht wiederholt
ignoreStatusCode: trueWird nicht als Fehler gewertet, und { status, body } wird als Ergebnis gebundenGreift nicht, es wird als Fehler behandelt
Try/catchIm catch behandelbarIm catch behandelbar

Die Bedingungen, unter denen die Dateiübertragung fehlschlägt, behandelt Eine Datei als Body senden im Detail.

Serverseitige Aggregation nur für die Anzahl

Die Anzahl zählt ResourceCount auf dem Server. Da dabei keine Elemente gelesen werden, gilt die Obergrenze für die Anzahl verarbeiteter Elemente hier nicht.

Für sum und group-by gibt es keine dedizierten Servervorgänge. Solche Aggregationen müssen Sie selbst berechnen, indem Sie mit ResourceForEach iterieren und mit SetVar und JsonLogic rechnen, weshalb Sie an die Obergrenze für die Anzahl verarbeiteter Elemente gebunden sind (für das Aggregieren von Millionen von Datensätzen ungeeignet). Wenn Sie nur die Anzahl brauchen, iterieren Sie nicht, sondern verwenden ResourceCount.

Kein Warten oder Verzögern

Ein Script hat kein Delay-Statement. Ein Script wird einmal ausgeführt und ist dann fertig und wartet oder pollt intern nicht, bis ein externer Job fertig ist.

Statische Einschränkungen (bei der Speicherung validiert)

Das Folgende wird geprüft, wenn ein Script gespeichert wird (beim Erstellen/Ändern). Bei einer Verletzung wird die Speicherung abgelehnt (der Fehler tritt zum Autorenzeitpunkt auf, nicht zur Laufzeit). Welche Verletzung mit welchem Code abgelehnt wird, behandelt der Abschnitt Fehler.

EinschränkungWert
Maximale externe Aufrufe (Http, EmailSend) pro DefinitionTarifabhängig (siehe Tarife)
Maximale Gesamtzahl verarbeiteter Elemente bei ResourceForEach (ohne deklariertes limit wird bis zu diesem Wert iteriert; verbleiben dabei Treffer, schlägt es fehl)10.000
Maximale SetVar pro Definition (inklusive verschachtelter)10
Maximale Cache pro Definition (inklusive verschachtelter, unabhängig von der Operation zusammengezählt)5. Bei Überschreitung Speichern abgelehnt
Cache im Block von Loop oder ResourceForEachSpeichern abgelehnt
Cache.keyNur Literal, maximal 128 Zeichen. Bei einem Wertausdruck Speichern abgelehnt
Cache.ttlZwischen 1 und 30 Sekunden, ohne Angabe 5 Sekunden. Außerhalb dieses Bereichs Speichern abgelehnt
Maximale Gesamtzahl an Statements pro Definition (inklusive verschachtelter)Tarifabhängig (siehe Tarife)
Obergrenze für Http.retry2
Anfrage-Body-Felder eines Http (body, urlBody, multipartBody)Nur eines der drei. Bei zwei oder mehr Speichern abgelehnt
Anzahl der parts in Http.multipartBodyMindestens 1. Wenn leer, Speichern abgelehnt
value und url eines multipartBody-partGenau eines. Wenn beide angegeben oder beide leer sind, Speichern abgelehnt
fileName eines multipartBody-partNur in einem part mit url. Ohne url angegeben Speichern abgelehnt
Länge von Regex.pattern128 Zeichen
Maximale secrets pro Definition20
key in secrets1-64 Zeichen, nur lateinische Buchstaben, Ziffern, _ und -. Bei zwei gleichen key Speichern abgelehnt
value in secrets1-4.096 Zeichen. Außerhalb dieses Bereichs Speichern abgelehnt
{ /secrets… }-ReferenzGenau /secrets/<deklarierter key>. Andernfalls Speichern abgelehnt
Ein Statement, das einen ServiceUser erstellt oder löschtSpeichern abgelehnt. Nur die drei Lese-Statements sowie ResourceUpdate und ResourcePatch nehmen diese Ressource an
createdBy: ":self" in where, wenn anonymousCallEnabled true istSpeichern abgelehnt
transformations einer Media-Ingest-Anweisung (Dateitransformation)Nur ein Array. Das type eines Elements ist PdfWatermark, color ist #RRGGBB. text ist in seinem gesamten geschriebenen String (einschließlich der Pfade in { /pointer }) eine einzelne Zeile aus zulässigen Zeichen. Bei einem Verstoß Speichern abgelehnt
Länge eines literalen text von PdfWatermark1-64 Zeichen. Außerhalb dieses Bereichs Speichern abgelehnt. Ein text mit { /pointer } wird beim Speichern nicht geprüft, sondern bei der Ausführung anhand des aufgelösten Werts

Die festen Limits in der Tabelle oben sind von der Plattform vorgegebene Werte und daher unabhängig vom Tarif gleich. Dagegen sind die Gesamtzahl der Statements und die Anzahl externer Aufrufe pro Definition tarifabhängige Limits. Diese beiden sind keine Validierungsfehler, sondern Tariflimits: Bei Überschreitung wird das Speichern bzw. Ändern wegen Überschreitung des Tariflimits abgelehnt (dieselbe Definition ist in einem höheren Tarif erlaubt) und durch ein Upgrade freigegeben. Die tarifabhängigen Zahlen finden Sie unter Tarife.

Der Media-Datei-Ingest wird, anders als externe Aufrufe wie Http und EmailSend, nicht auf das Limit für externe Aufrufe pro Definition angerechnet.

ResourceForEach ist ein zusammengesetztes Statement mit eigenen Kindern und wird daher selbst nicht auf die Anzahl externer Aufrufe angerechnet. Gezählt werden die externen Aufruf-Statements (Http, EmailSend) in onEach (statisch als 1 gezählt, aber bei der Iteration pro Element tatsächlich ausgeführt). onEach kann externe Aufrufe oder einen Media-Datei-Ingest enthalten, und das gilt ebenso für den body von Loop. Wie oft eine Iteration tatsächlich läuft, geht nicht in diese Zählung ein, sondern kommt stattdessen unten im Zeitbudget als Multiplikation zum Tragen.

Obergrenzen für Wertlängen (Laufzeit)

Die Statements für Signatur und Textverarbeitung sowie Cache haben eine Obergrenze für die Größe des Werts, den sie behandeln. Gemeint ist nicht die Länge des Ausdrucks, sondern die Länge des Werts, zu dem der Ausdruck aufgelöst wird (die sechzehn Zeichen { /rawPayload } zeigen auf mehrere Dutzend KB), und deshalb wird sie nicht beim Speichern, sondern während der Ausführung geprüft.

ZielObergrenzeBei Überschreitung
Das value von Signature65.536 ZeichenDieses Statement schlägt fehl (status 422)
Das value von Hash128 ZeichenDieses Statement schlägt fehl (status 422)
Das value von Regex10.240 Zeichen (10KiB)Dieses Statement schlägt fehl (status 400)
Das value von Cache10.240 Byte (10KiB)Dieses Statement schlägt fehl (status 422)
  • Alle vier sind wie jeder andere Laufzeitfehlschlag und lassen sich daher mit Try/catch lokal behandeln.
  • Die Obergrenze von Signature ist an der Body-Größe ausgerichtet, die reale Anbieter senden (Zahlungsereignisse liegen bei einigen KB, Bestell-Webhooks erreichen mehrere Dutzend KB). Hash ist die Stelle, an der einige Felder aneinandergehängt werden, und daher viel enger.
  • Die 128 Zeichen von Regex.pattern sind die Prüfung beim Speichern aus den Statischen Einschränkungen oben. Diese Länge ist keine Vorrichtung gegen ein Durchdrehen des Patterns ((a+)+$ ist auch mit sechs Zeichen gefährlich). Dagegen wirken die Regel, dass ein Pattern nur als Literal geschrieben werden darf, und das Zeitbudget unten; die Länge verspricht nur eine Größe, die ein Mensch lesen und prüfen kann.

Zeitbudget (Laufzeit)

Die für eine einzelne Ausführung erlaubte Zeit beträgt höchstens 180 Sekunden. Die tatsächlich erlaubte Zeit richtet sich nach der Script-Definition (beim Senden von Dateien auch nach dem Tarif) und ergibt sich aus den grundlegenden 30 Sekunden plus der Zeit, die externe Aufrufe nutzen können.

Dieses Budget gilt für die gesamte Ausführung. Davon unabhängig muss eine einzelne Http-Anfrage innerhalb ihres timeoutMs abgeschlossen sein.

Grundbudget von 30 Sekunden

Alle Arbeiten, die keine externen Aufrufe sind, etwa das Lesen und Schreiben von Ressourcen oder das Empfangen und Verarbeiten einer Media-Datei, werden innerhalb dieser 30 Sekunden erledigt. Einem Script ohne externe Aufrufe werden 30 Sekunden gewährt.

Zeit, die pro Statement hinzukommt

Die Zeiten hintereinander stehender Statements werden alle addiert.

StatementHinzukommende Zeit
HttptimeoutMs (ohne Angabe 30 Sekunden). Beim Senden von Dateien wird pro Datei die Download-Zeit (Tabelle unten) addiert, und ist retry angegeben, wird das Ganze mit der Anzahl der Versuche (1 + retry) multipliziert
EmailSendtimeoutMs (ohne Angabe 10 Sekunden). Da nicht wiederholt wird, wird die Zeit nur einmal addiert
IfDie Zeit des längeren der beiden Zweige then und else
ParallelDie Zeit des längsten unter den branches
TryDie Summe der Zeiten von body, catch und finally
LoopDie Zeit von body multipliziert mit maxIterations (ohne Angabe 10.000)
ResourceForEachDie Zeit von onEach multipliziert mit limit (ohne Angabe 10.000)
Andere Statements (die keine anderen Statements enthalten)Es wird nichts addiert. Sie werden innerhalb des Grundbudgets von 30 Sekunden erledigt

Enthält eine Iteration keinen externen Aufruf, bleibt die hinzukommende Zeit auch nach der Multiplikation mit der Anzahl der Iterationen 0. Eine solche Iteration muss daher innerhalb des Grundbudgets von 30 Sekunden abgeschlossen sein.

Download-Zeit pro Datei

PlanDownload-Zeit
Freeetwa 5,2 Sekunden
Basicetwa 10,5 Sekunden
Proetwa 10,5 Sekunden
Enterpriseetwa 107,4 Sekunden

Dieser Wert ist die Zeit, die nötig ist, um die Datenmenge des Download-Limits des Tarifs mit 10.000.000 Byte pro Sekunde zu empfangen.

Rechenbeispiel

Ein Script, das im Pro-Tarif ein Http aufruft, das zwei Fotos sendet (timeoutMs 30 Sekunden, retry 1), wird wie folgt berechnet.

  • Http: (30 Sekunden + 10,5 Sekunden × 2) × 2 = etwa 102 Sekunden
  • Gesamte Ausführung: 30 Sekunden + 102 Sekunden = etwa 132 Sekunden

132 Sekunden sind kürzer als 180 Sekunden, daher werden diesem Script 132 Sekunden gewährt.

Wenn 180 Sekunden überschritten werden

Auch wenn der berechnete Wert 180 Sekunden überschreitet, wird das Script gespeichert und ausgeführt. Erreicht die Ausführung jedoch 180 Sekunden, wird sie an diesem Punkt abgebrochen.

Anzahllimits pro Plan

Bei einem Script ist die Anzahl pro Organization je nach Plan begrenzt.

PlanScript-Anzahl
Free10
Basic30
Pro100
EnterpriseUnbegrenzt

Davon getrennt sind auch die Anzahl der Statements und der externen Aufrufe (Http, EmailSend), die eine Script-Definition enthalten kann, je nach Tarif begrenzt. Überschreitet eine Definition beim Speichern oder Ändern das Limit dieses Tarifs, wird sie abgelehnt; die konkreten Zahlen finden Sie unter Tarife.

Wenn das Limit erreicht ist, wird das Erstellen eines neuen Script abgelehnt.

Größe von Http-Dateidownloads

Wenn Http eine Datei, die als Anfrage-Body gesendet werden soll, von einer URL abruft (urlBody, der url-part von multipartBody), ist die Größe, die pro Datei-URL empfangen werden kann, je nach Tarif begrenzt. Maßgeblich ist der Tarif der Organization, zu der der Space gehört, dem das Script gehört.

PlanMaximale Größe pro Datei-URL
Free50MiB
Basic100MiB
Pro100MiB
Enterprise1GiB
  • Das Limit gilt für jede URL einzeln. Gibt es mehrere url-parts, muss jede Datei innerhalb dieses Limits liegen.
  • Wird versucht, eine Datei zu senden, die das Limit überschreitet, schlägt dieses Http fehl (siehe Zwei Arten, wie Http fehlschlägt).
  • Dieses Limit ist auch die Grundlage für die Download-Zeit, die zum Zeitbudget addiert wird.

Sicherheitsmodell

secrets

Geheimwerte wie externe API-Schlüssel, der Secret Key eines Zahlungsdienstleisters (PG), Webhook-Signaturschlüssel oder ein vorab berechneter Basic …-Authentifizierungswert werden nicht wörtlich in ein Statement geschrieben. Sie deklarieren sie in den secrets der Definition und lesen sie im Statement mit { /secrets/<key> }. Auch öffentlich bekannte Testschlüssel legen Sie an derselben Stelle ab. Wenn Sie dann auf den echten Schlüssel umstellen, bleiben die Statements unverändert, und Sie ändern nur den Wert in secrets.

"secrets": [
  { "key": "LLM_API_KEY",            "value": "sk-...",    "description": "API-Schlüssel für LLM-Aufrufe" },
  { "key": "WEBHOOK_SIGNING_SECRET", "value": "whsec_...", "description": "" }
],
"statements": [
  { "type": "Http", "method": "POST", "url": "https://api.openai.com/v1/chat/completions",
    "headers": [ { "key": "Authorization", "value": "Bearer { /secrets/LLM_API_KEY }" } ],
    "body": { /* ... */ }, "name": "llm" }
]
FeldErforderlichRegel
keyErforderlich1-64 Zeichen, nur lateinische Buchstaben, Ziffern, _ und -. Muss innerhalb eines Script eindeutig sein.
valueErforderlichEin String mit 1-4.096 Zeichen. Er ist ein statischer Wert und wird nicht als Template ausgewertet; ein darin stehendes { /… } wird also wörtlich verwendet.
descriptionErforderlichDie Beschreibung des Zwecks, 0-128 Zeichen. Auch ein leerer String "" ist zulässig.
  • Speichern: WEEGLOO verschlüsselt value und speichert es sicher. Ein Statement liest mit { /secrets/<key> } den ursprünglichen Wert.
  • Abfrage: In API-Antworten, die ein Script zurückgeben (Abfrage, Erstellen, Ändern), wird value als ursprünglicher Wert zurückgegeben. Rollen, die dieses Script lesen können, sehen den Wert, halten Sie die Leseberechtigung daher eng. Mitglieder (ServiceUser) können eine Script-Definition nicht lesen (Abfrage und Autorenschaft sind CMA-exklusiv, und auf der ACMA gibt es keine Script-API).
  • Ändern: Eine vollständige Änderung (PUT) ersetzt die gesamte Definition. Senden Sie sie ohne secrets, werden die deklarierten Geheimwerte gelöscht; verweist ein Statement noch mit { /secrets/… } auf einen dieser Werte, wird das Speichern abgelehnt. Senden Sie secrets deshalb bei jeder Änderung mit. Es genügt, die Werte aus der Abfrageantwort unverändert zurückzusenden.
  • Der Wert während der Ausführung: Was mit dem gelesenen Wert geschieht, bestimmt das Statement. Geben Sie ihn mit Return zurück, bleibt er in der Ausführungsantwort und im ScriptLog erhalten; legen Sie ihn in SetVar, Cache oder Content ab, bleibt er dort als ursprünglicher Wert stehen. Senden Sie einen Geheimwert nur an die externe API, die ihn benötigt.
  • App Bundle: Wird ein Script in ein App Bundle gepackt, wird das value in secrets durch ****** verdeckt, während key und description unverändert übernommen werden. Ein Script, das durch die Installation dieses App Bundle entsteht, enthält die Geheimwerte im Zustand ******. Erst wenn die installierende Seite die echten Werte einträgt, funktionieren die Statements, die diese Werte lesen. Werte, die außerhalb von secrets stehen (die Header von Http, das secret von Signature usw.), werden nicht verdeckt, sondern unverändert übernommen.

Ein Script kann bis zu 20 secrets enthalten. Die Pointer-Regeln werden unter /secrets in den Wertausdrücken behandelt.

Ausführungsidentität und Autorisierung

  • Ausführungsidentität: Während der Ausführung wird jeder Ressourcenvorgang unter der Identität des Benutzers ausgeführt, der /execute aufgerufen hat. Der createdBy/updatedBy einer erstellten oder geänderten Ressource ist der Aufrufer, und auch ein createdBy: ":self"-Scope wird anhand des Aufrufers aufgelöst. Die Ausnahme ist der anonyme Aufruf. Eine Ausführung, die über /execute/anonymous hereinkommt, hat keinen Aufrufer, daher werden beide anhand des Autors aufgelöst (Anonymer Aufruf).
  • Es gibt zwei Autorisierungsgrenzen, und zur Laufzeit prüft die Engine die Ressourcenberechtigungen nicht pro Statement erneut.
    1. Zum Autorenzeitpunkt (Speicherung): Beim Speichern eines Script wird geprüft, ob der Autor die von seinen Statements verwendeten Ressourcen- und Aktionsberechtigungen tatsächlich besitzt. Fehlt auch nur eine, wird die Speicherung abgelehnt. Mit anderen Worten: Ein Script, das einen unautorisierten Vorgang enthält, wird von vornherein nicht gespeichert. Diese Prüfung erhält jedes Statement, das eine Ressource auswählt, ob Leaf oder blockbesitzendes ResourceForEach. Auch eine schon gespeicherte Definition wird beim Ändern erneut geprüft, sodass sich eine Definition nach dem Entzug der Berechtigung nicht mehr ändern und speichern lässt.
      • Das Mitgliederverzeichnis (ServiceUser) wird nicht über die Berechtigungs-Map, sondern über die Einstellungsachse geprüft. Um in den drei Lese-Statements sowie in ResourceUpdate und ResourcePatch resource: "ServiceUser" zu verwenden, müssen die settings der SpaceRole des Autors SETTING_SERVICE_LOGIN (oder SETTING_ALL) enthalten (siehe settings der SpaceRole). Denn das Mitgliederverzeichnis ist auch auf allen anderen Wegen eine Ressource, die von den Space-Einstellungen verwaltet wird.
      • Ein Statement, das ein Mitglied erstellt oder löscht, lässt sich mit keiner Rolle speichern. Da ein Script ein Mitglied nicht erstellen oder löschen kann, wird es nicht wegen fehlender Berechtigung (403), sondern als falsch geschriebenes Statement (400) abgelehnt. Es ist also keine Lücke, die man mit zusätzlichen Berechtigungen schließen kann. Die einzigen erlaubten Änderungen sind roleOverride und enableLogin über ResourceUpdate und ResourcePatch (Mit dem Mitgliederverzeichnis arbeiten).
    2. Zum Aufrufzeitpunkt (/execute): Es wird nur die Execute-Berechtigung des Aufrufers auf das Script geprüft. Ohne sie ergibt sich 403. Nach bestandener Prüfung werden die Ressourcenberechtigungen pro Statement zur Laufzeit nicht erneut überprüft, und die Ausführung läuft. Das funktioniert wie die Berechtigung zum Ausführen einer Funktion in der Programmierung. Wer die Berechtigung hat, die Funktion auszuführen, wird nach der Berechtigung für die einzelnen Vorgänge darin nicht erneut gefragt. Auf dem Weg des anonymen Aufrufs gibt es diese Prüfung nicht. Denn es gibt keinen Aufrufer, den man prüfen könnte, und deshalb ist das Öffnen dieses Wegs dasselbe wie ein Script ohne Authentifizierung zu veröffentlichen.
  • Blockieren des direkten Aufrufs (directCallEnabled): Ist das directCallEnabled eines Script false, wird bereits der direkte /execute-Aufruf selbst abgelehnt. Dieses Gate greift erst, nachdem die Prüfung der Execute-Berechtigung bestanden ist, und blockiert daher auch dann, wenn die Execute-Berechtigung vorhanden ist. Ein Aufrufer ohne Execute-Berechtigung erhält bereits 403, bevor der Aufruf dieses Gate erreicht. Dieses Gate gibt es nur an diesem Endpunkt, daher führen die Anbindungsaktion (script) eines Webhook und ein Scheduler das Script unverändert aus. Der Standardwert ist true (direkter Aufruf erlaubt).
  • Anonymer Aufruf (anonymousCallEnabled): Der Standardwert ist false. Setzen Sie ihn auf true, wird nur dieses Script auch über einen eigenen Weg ohne Authentifizierung (/execute/anonymous) ausgeführt, und die Ausführungsidentität ist dann nicht der Aufrufer, sondern der Autor. Von den beiden Grenzen oben fehlt auf diesem Weg die Prüfung zum Aufrufzeitpunkt (Execute-Berechtigung), daher übernimmt das Script die tatsächliche Authentifizierung selbst (die Signaturprüfung der empfangenen Anfrage). Die Bedingungen zum Einschalten und die Speicherregeln werden unter Anonymer Aufruf behandelt.
  • Eigentümer-Scope: createdBy: ":self" in einem where-Filter bedeutet "nur das, was der aktuelle Aufrufer erstellt hat" (z. B. nur die eigene Wallet abfragen). In einem Script, das anonyme Aufrufe erlaubt, lässt sich dieser Filter nicht verwenden. Da es keinen Aufrufer gibt und er zum Autor aufgelöst wird, trifft die ursprüngliche Bedeutung eines Eigentümer-Scope nicht mehr zu.
  • Delegierte Berechtigungen (Vorsicht für Autoren): Verbindet man die beiden obigen Grenzen, ist das Ausführen eines Script gleichbedeutend mit einem Handeln mit den an das Script delegierten Berechtigungen des Autors. Der Aufrufer braucht nur Execute, und die Statements innerhalb des Script laufen genau in dem Umfang, für den der Autor bei der Speicherung autorisiert war. Dadurch kann ein Ressourcenvorgang, den der Aufrufer selbst nicht durchführen könnte, dennoch über das Script geschehen. Da die dem Autor erteilten Berechtigungen die effektive Reichweite dieses Script bestimmen, überlegen Sie sorgfältig, welche Vorgänge Sie in ein Script aufnehmen.

Zusammenfassende Checkliste

Prüfen Sie vor dem Speichern Folgendes.

  • Haben Sie den anonymen Aufruf (anonymousCallEnabled) eingeschaltet, steht in where kein createdBy: ":self", und ein Statement, das die empfangene Anfrage prüft (etwa Signature), steht an erster Stelle.
  • Die externen Aufrufe (Http, EmailSend) und die Gesamtzahl der Statements liegen innerhalb des Tariflimits, SetVar ist höchstens 10 und Cache höchstens 5.
  • Wenn Sie Cache verwendet haben, haben Sie key als Literal geschrieben und es nicht innerhalb von Loop oder ResourceForEach platziert.
  • Wenn Sie mit ResourceForEach eine große Menge durchlaufen, haben Sie ein limit deklariert oder geprüft, dass die Menge vollständig durchlaufbar ist.
  • Haben Sie eine Iteration (Loop, ResourceForEach) aufgenommen, haben Sie geprüft, dass diese Iteration als Multiplikation in das Zeitbudget eingeht (ohne externen Aufruf ist das Grundbudget von 30 Sekunden die Grenze).
  • Geheimwerte wie externe API-Schlüssel oder Signaturschlüssel haben Sie in secrets deklariert und mit { /secrets/<key> } gelesen. Kein Geheimwert steht wörtlich in einem Statement.
  • Wenn Sie mit einer vollständigen Änderung (PUT) speichern, haben Sie secrets mitgesendet.
  • Die Nachricht für die Signaturprüfung haben Sie nicht über /payload, sondern über { /rawPayload } genommen.
  • Gibt es ein Statement, das mit einem Mitglied (ServiceUser) arbeitet, besitzt der Autor SETTING_SERVICE_LOGIN, und ein Statement, das diese Ressource erstellt oder löscht, haben Sie nicht aufgenommen.
  • Nicht rückgängig zu machende Vorgänge (externe Aufrufe) wurden möglichst weit hinten platziert.
  • Wenn Sie mit Http Dateien senden, haben Sie nur eines der Anfrage-Body-Felder (body, urlBody, multipartBody) angegeben und geprüft, dass jede Datei innerhalb des Download-Limits pro Tarif liegt.
  • Wenn Sie Update-/Patch-Konkurrenz befürchten, verwenden Sie das version-Feld von ResourceUpdate oder ResourcePatch.
  • Um ein Ergebnis zurückzugeben, haben Sie Return.value angegeben.

Fehler

Dies sind die Codes, die auftreten, wenn die Form der Definition eine statische Einschränkung verletzt und das Speichern deshalb abgelehnt wird. Die Codes für Verstöße gegen die Regeln der Wertausdrücke stehen unter Fehler bei den Wertausdrücken, die Codes, die beim Aufrufen und Löschen auftreten, unter Fehler bei den Endpunkten. Codes, die allen Ressourcen gemeinsam sind, finden Sie unter Gemeinsame Fehler.

CodeBedingung
WGL400066Eine Definition enthält mehr als 5 Cache-Statements.
WGL400068Ein Cache-Statement steht im Block von Loop oder ResourceForEach.
WGL400067Im key eines Cache-Statements steht kein Literal, sondern eine { /pointer }-Referenz.
WGL400065Das ttl eines Cache-Statements liegt außerhalb des erlaubten Bereichs.
WGL400063In einem Cache-Statement steht ein Feld, das nicht zur jeweiligen action gehört (ttl bei Get, defaultValue bei Set).
WGL400060Im resource von ResourceCreate, ResourceDelete oder eines Statements für Veröffentlichung und Archivierung steht "ServiceUser". Das Mitgliederverzeichnis nehmen nur die drei Lese-Statements sowie ResourceUpdate und ResourcePatch an.
WGL400077Im resource von ResourceCount steht eine Ressource, die sich nicht zählen lässt. Media und das Mitgliederverzeichnis (ServiceUser) lassen sich nicht zählen.
WGL400037In einem EmailSend stehen to und toServiceUser zugleich, oder beide sind leer. Schreiben Sie genau eines davon.
WGL400054Die Summe der Empfänger eines EmailSend (to 1 + cc + bcc) überschreitet 50.
WGL400039Das timeoutMs eines EmailSend überschreitet die Obergrenze.
WGL400101In einem EmailSend stehen body und templateBody zugleich, oder beide sind leer. Schreiben Sie genau eines davon.
WGL400102Das templateBody.source eines EmailSend ist nicht genau ein Pointer auf ein Content, das ein ResourceRead oder ein ResourceFind dieses Script gelesen hat. Auch Zeichen vor oder hinter dem Pointer führen zur Ablehnung.
WGL400061In einem Script, das anonyme Aufrufe erlaubt (anonymousCallEnabled), steht im where eines Lese-Statements createdBy: ":self".
WGL400023Eine Definition enthält mehr als 10 SetVar-Statements.
WGL400026Das retry eines Http-Statements überschreitet die Obergrenze 2.
WGL400087In einem Http stehen zwei oder mehr Anfrage-Body-Felder (body, urlBody, multipartBody).
WGL400088Das multipartBody eines Http enthält keinen einzigen part.
WGL400089In einem part von multipartBody stehen sowohl value als auch url, oder keines von beiden.
WGL400090In einem part von multipartBody steht fileName ohne url.
WGL400036ResourceForEach überschreitet die Obergrenze für die Anzahl der Elemente, die dieses Statement verarbeiten kann.
WGL400094In secrets gibt es zwei oder mehr Einträge mit demselben key.
WGL400095Eine Definition enthält mehr als 20 secrets.
WGL400086Das value eines secrets-Eintrags liegt außerhalb von 1-4.096 Zeichen. Der Fehler enthält das value nicht.
WGL400086Das text eines PdfWatermark ohne { /pointer } liegt außerhalb von 1-64 Zeichen.
WGL400096Die transformations einer Media-Ingest-Anweisung sind kein Array, das type eines Elements ist nicht PdfWatermark, bei PdfWatermark fehlt text oder ist ein Objekt oder Array, color hat nicht das Format #RRGGBB, oder das text in seiner geschriebenen Form enthält unzulässige Zeichen oder einen Zeilenumbruch.
WGL429005Die Gesamtzahl der Statements in einer Definition überschreitet das Tariflimit.
WGL429006Die Anzahl der externen Aufrufe (Http, EmailSend) in einer Definition überschreitet das Tariflimit.
WGL403015Der Autor besitzt die Berechtigungen für die Ressourcen und Aktionen nicht, die die Statements der Definition verwenden. Selbst wenn die Berechtigung vorliegt, wird das Speichern abgelehnt, sobald an dieser Erlaubnis ein Filter contentType, createdBy oder tag hängt. Es muss eine Erlaubnis ohne Bedingung sein. Die einzige Ausnahme ist Content Create: Hier wird auch eine Erlaubnis anerkannt, die einen contentType-Bereich festlegt, und dieser Bereich wird mit dem im Statement angegebenen contentType abgeglichen (für Media Create gilt diese Ausnahme nicht). Denselben Code erhalten Sie auch, wenn im resource eines Lese-Statements "ServiceUser" steht, der Autor aber SETTING_SERVICE_LOGIN nicht besitzt.