実行セマンティクス、制約、セキュリティ

Script が ランタイムでどのように動作するか(順序、トランザクション、エラー、ロック)、保存時にどのような静的制約を受けるか、そして セキュリティモデルを整理します。文法は Statement カタログ と 値式、実践的な組み合わせは クックブック を参照してください。

実行順序

  • statements は 上から下へ順次実行されます。Return に到達すると、その時点で終了します。
  • 実行は、呼び出しリクエストを処理する経路でインラインに行われます。 呼び出しのレスポンスがそのまま実行結果であり(レスポンスの形は Script 概要のリクエストとレスポンス を参照)、1 回の実行に与えられる時間は下の 時間予算 で扱います。

実行セマンティクス

Guard(事前条件)

専用の guard Statement はありません。If と then:[Return] で表現します。条件に違反した場合は結果を返し、以降の Statement は実行しません(guard のない Script も当然可能です)。

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

トランザクションなしと best-effort 補償

Script は トランザクションではありません。 失敗した場合、エンジンはそれまでに行った操作の補償(compensation)を試み、エラーの原因を返しますが、次の制限があります(設計上許容しています)。

  • 削除の取り消しは新しい sys.id を作るため、これを指していた参照が壊れます。
  • 外部効果(Http)は不可逆です(すでに送信された呼び出しと課金は取り消せません)。
  • 補償がまったく実行されず、未補償の状態が残ることがあります。

真の原子性が必要な場合は、ユーザーが Script で直接補償するか、取り消せない操作(外部呼び出しなど)を最後に配置します。「連鎖はできるがロールバックはできず、しかも安全に見える」順序が最も危険です。

楽観的ロック

update/patch の競合は ResourceUpdate と ResourcePatch の version で絞ります。version(値式、Int)を渡すと、対象の現在の sys.version と 一致する場合のみ更新し、不一致の場合は バージョン競合エラーで abort されます(Try/catch で局所的に処理できます)。省略すると検査なしの last-write-wins になります。通常は ResourceRead や ResourceFind で先に読み込み、その sys.version を渡します(クックブックの楽観的ロック CAS を参照)。

origin 基準の書き込み

書き込みは常に origin(draft)に反映され、delivery(CDA/ACDA)への公開は publish で制御します(ResourceCreate/ResourceUpdate/ResourcePatch の publish、または ResourcePublish/ResourceUnpublish)。

何が失敗か

実行中に Statement が 1 つ失敗すると、その失敗を処理する Try がない限り、実行はその場で中断されます。このときエンジンは、それまでに行った操作を取り消そうと試みます。取り消しには限界があり、詳しくは トランザクションなしと best-effort 補償 で扱います。

失敗した Statement が Try の中にあれば、その失敗を catch で処理できます。catch の中では /error で失敗の内容({ message })を参照します。どの Statement で失敗したかは含まれません。

次の場合が失敗として扱われます。

Return は失敗ではありません。実行を正常に早く終えるものなので、catch には移りません。

Http が失敗する 2 つの方式

Http の失敗は、status 応答として処理されるかどうかによって 2 つに分かれます。この違いによって、retry と ignoreStatusCode が適用されるかどうかが変わります。

区分status 応答として処理される場合ただちに失敗する場合
該当する場合対象 API が 400 以上の status を応答した場合、タイムアウトした場合(status 504)、対象 API に接続できなかったか応答を読み取れなかった場合(status 502)、応答本文が 10MiB を超える場合(status 502)responseType が "Json" なのに成功応答の本文が JSON ではない場合、送るファイルがダウンロード上限を超える場合、ファイル URL が 2xx 以外の status を応答した場合やファイル URL に接続できない場合、part の値の形式が誤っている場合
retry指定した回数だけ再試行します再試行しません
ignoreStatusCode: true失敗とみなさず { status, body } を結果としてバインドします適用されず、失敗として扱われます
Try/catchcatch で処理できますcatch で処理できます

ファイル送信の過程で失敗する条件は ファイルを本文として送る で詳しく扱います。

サーバー側集計は件数のみ

件数は ResourceCount がサーバー側で数えます。項目を読み取ってこないため、処理項目数の上限を受けません。

sum と group-by には専用のサーバー操作がありません。そうした集計は ResourceForEach で巡回しながら SetVar と JsonLogic で自分で計算する必要があり、そのため 処理項目数の上限に縛られます(数百万件の集計には不向きです)。件数だけが必要なら、巡回せずに ResourceCount を使います。

待機と遅延なし

Script には Delay Statement はありません。Script は 一度実行されて終わりであり、外部 job が終わるまで内部で待機したりポーリングしたりしません。

静的制約(保存時の検証)

以下は Script を 保存(作成/更新)する時点で検査されます。違反すると保存が拒否されます(ランタイムではなく作成時の失敗です)。どの違反がどのコードで拒否されるかは エラー で扱います。

制約値
定義ごとの 外部呼び出しの最大数(Http・EmailSend)プランごと(料金プラン 参照)
ResourceForEach の 総処理項目数の最大(宣言した limit がなければこの値まで巡回、マッチが残ったまま達すると失敗)10,000
定義ごとの SetVar の最大数(ネスト含む)10
定義ごとの Cache の最大数(ネスト含む、演算に関係なく合算)5。超えると保存を拒否
Loop・ResourceForEach のブロック内の Cache保存を拒否
Cache.keyリテラルのみ、最大 128 文字。値式であれば保存を拒否
Cache.ttl1 から 30 秒のあいだ、省略時は 5 秒。外れると保存を拒否
定義ごとの 全 Statement の最大数(ネスト含む)プランごと(料金プラン 参照)
Http.retry の上限2
1 つの Http のリクエスト本文フィールド(body・urlBody・multipartBody)3 つのうち 1 つのみ。2 つ以上書くと保存を拒否
Http.multipartBody の part 数1 個以上。空であれば保存を拒否
multipartBody part の value・urlちょうど 1 つ。両方書くか両方空にすると保存を拒否
multipartBody part の fileNameurl を書いた part のみ。url なしで書くと保存を拒否
Regex.pattern の長さ128 文字
定義ごとの secrets の最大数20
secrets の key1〜64 文字、英字・数字・_・- のみ。同じ key が 2 つあれば保存を拒否
secrets の value1〜4,096 文字。外れると保存を拒否
{ /secrets… } の参照正確に /secrets/<宣言した key>。そうでなければ保存を拒否
ServiceUser を 作る・消す Statement保存を拒否。読み取りの 3 つの Statement と ResourceUpdate・ResourcePatch だけがこのリソースを受け取ります
anonymousCallEnabled が true の場合の where の createdBy: ":self"保存を拒否
Media インジェスト指示の transformations(ファイル変換)配列のみ。要素の type は PdfWatermark、color は #RRGGBB。text は書いた文字列全体({ /pointer } のパスを含む)が使える文字からなる 1 行。違反すると保存を拒否
PdfWatermark のリテラル text の長さ1〜64 文字。外れると保存を拒否。{ /pointer } を含む text は保存時には検査せず、実行時に resolve された値で検査

上の表の固定上限はプラットフォームが定めた値なので、プランに関係なく同じです。一方、定義ごとの全 Statement 数と外部呼び出し数はプランごとの上限です。この二つは妥当性エラーではなくプランの上限なので、超えると保存・更新がプラン上限超過で拒否され(同じ定義でも上位プランでは許可)、アップグレードで解除されます。プランごとの数値は 料金プラン にあります。

Media ファイルのインジェストは、Http・EmailSend のような外部呼び出しとは異なり、定義ごとの外部呼び出しの上限には含まれません。

ResourceForEach は子を所有する複合 Statement なので、それ自体は外部呼び出しの数には数えません。 onEach 内の外部呼び出し Statement(Http・EmailSend)が数えられます(静的には 1 として数えますが、巡回して項目ごとに実際に実行されます)。onEach には外部呼び出しや Media ファイルのインジェストを含められ、これは Loop の body も同じです。反復が実際に何回まわるかはこのカウントには入らず、代わりに下の 時間予算 で掛け算として入ります。

値の長さの上限(ランタイム)

署名とテキスト処理の Statement、そして Cache は、扱う値の大きさに上限があります。式の長さではなく、その式が resolve された値の長さであり({ /rawPayload } の 16 文字が数十 KB を指します)、そのため保存の時点ではなく実行中に検査されます。

対象上限超えると
Signature の value65,536 文字その Statement が失敗(status 422)
Hash の value128 文字その Statement が失敗(status 422)
Regex の value10,240 文字(10KiB)その Statement が失敗(status 400)
Cache の value10,240 バイト(10KiB)その Statement が失敗(status 422)
  • 4 つとも他のランタイム失敗と同じなので、Try/catch で局所的に処理できます。
  • Signature の上限は、実際のプロバイダーが送ってくる本文の大きさに合わせたものです(決済イベントは数 KB、注文の Webhook は数十 KB に達します)。Hash はフィールドをいくつかつなげる箇所なので、はるかに狭いです。
  • Regex.pattern の 128 文字は、上の 静的制約 にある保存時の検査です。この長さは暴走を防ぐ仕掛けではありません((a+)+$ は 6 文字でも危険です)。暴走を防ぐのは、パターンをリテラルとしてのみ書かせる規則と下の時間予算であり、長さが約束するのは人が読んで検討できる大きさだけです。

時間予算(ランタイム)

1 回の実行に許される時間は最大 180 秒です。実際に許される時間は Script の定義(ファイルを送る場合はプランも)によって決まり、基本の 30 秒に外部呼び出しが使える時間を足した値です。

この予算は実行全体に適用されます。これとは別に、Http リクエスト 1 回はそのリクエストの timeoutMs 以内に終わる必要があります。

基本の 30 秒

リソースの読み取りと書き込みや、Media ファイルを受け取って処理する作業のように、外部呼び出しではない作業はすべてこの 30 秒の中で処理されます。外部呼び出しのない Script には 30 秒が許されます。

Statement ごとに加算される時間

順に並んだ Statement の時間はすべて足します。

Statement加算される時間
HttptimeoutMs(指定しなければ 30 秒)。ファイルを送る場合はファイルごとにダウンロード時間(下の表)を足し、retry を指定した場合は全体に試行回数(1 + retry)を掛けます
EmailSendtimeoutMs(指定しなければ 10 秒)。再試行しないため 1 回だけ足します
Ifthen と else のうち長いほうの時間
Parallelbranches のうち最も長いものの時間
Trybody、catch、finally の時間をすべて足した値
Loopbody の時間に maxIterations(指定しなければ 10,000)を掛けた値
ResourceForEachonEach の時間に limit(指定しなければ 10,000)を掛けた値
その他の Statement(他の Statement を含まないもの)足しません。基本の 30 秒の中で処理されます

繰り返しの中に外部呼び出しがなければ、繰り返し回数を掛けても加算される時間は 0 です。したがって、そうした繰り返しは基本の 30 秒以内に終わる必要があります。

ファイル 1 つあたりのダウンロード時間

Planダウンロード時間
Free約 5.2 秒
Basic約 10.5 秒
Pro約 10.5 秒
Enterprise約 107.4 秒

この値は、プランの ダウンロード上限 に相当するデータを毎秒 10,000,000 バイトで受け取るのにかかる時間です。

計算例

Pro プランで写真 2 枚を送る Http(timeoutMs 30 秒、retry 1)を 1 つ呼び出す Script は、次のように計算します。

  • Http: (30 秒 + 10.5 秒 × 2) × 2 = 約 102 秒
  • 実行全体: 30 秒 + 102 秒 = 約 132 秒

132 秒は 180 秒より短いため、この Script には 132 秒が許されます。

180 秒を超える場合

計算した値が 180 秒を超えても、Script は保存されて実行されます。ただし、実行が 180 秒に達するとその時点で中断されます。

プランごとの個数上限

Script は Organization ごとの個数がプランごとに制限されます。

PlanScript の個数
Free10
Basic30
Pro100
Enterprise無制限

これとは別に、1 つの Script 定義が含められる Statement 数と外部呼び出し(Http・EmailSend)数もプランごとに制限されます。定義を保存・更新するときにそのプランの上限を超えると拒否され、具体的な数値は 料金プラン を参照してください。

上限に達すると新しい Script の作成が拒否されます。

Http ファイルのダウンロードサイズ

Http がリクエスト本文として送るファイルを URL から取得するとき(urlBody、multipartBody の url part)、ファイル URL 1 つあたりに受け取れるサイズがプランごとに制限されます。その Script を所有する Space が属する Organization のプランに従います。

Planファイル URL 1 つあたりの最大サイズ
Free50MiB
Basic100MiB
Pro100MiB
Enterprise1GiB
  • 上限は URL ごとに個別に適用されます。url part が複数あれば、各ファイルがこの上限以内である必要があります。
  • 上限を超えるファイルを送ろうとすると、その Http が失敗します(Http が失敗する 2 つの方式 参照)。
  • この上限は、時間予算 に加算されるダウンロード時間の基準でもあります。

セキュリティモデル

secrets

外部 API キー、決済代行会社(PG)のシークレットキー、Webhook の署名鍵、事前に計算した Basic … 認証値のようなシークレット値は、Statement に値をそのまま書きません。定義の secrets に宣言し、Statement では { /secrets/<key> } で読みます。公開されているテストキーも同じ場所に置きます。そうすれば、実際のキーに替えるときに Statement はそのままにして、secrets の値だけを替えれば済みます。

"secrets": [
  { "key": "LLM_API_KEY",            "value": "sk-...",    "description": "LLM 呼び出し用の API キー" },
  { "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" }
]
フィールド必須ルール
key必須1〜64 文字で、英字・数字・_・- のみを使います。1 つの Script の中で一意でなければなりません。
value必須1〜4,096 文字の文字列です。静的な値なのでテンプレートとして解釈されず、中に { /… } を入れても文字どおりに使われます。
description必須用途の説明で、0〜128 文字です。空文字列 "" も使えます。
  • 保存: value は WEEGLOO が暗号化して安全に保存します。Statement は { /secrets/<key> } で元の値を読みます。
  • 照会: Script を返す API レスポンス(照会・作成・更新)には、value が元の値のまま返されます。その Script を読める役割には値が見えるため、読み取り権限を狭くしておきます。会員(ServiceUser)は Script の定義を読めません(照会とオーサリングは CMA 専用であり、ACMA には Script API がありません)。
  • 更新: 全体更新(PUT)は定義全体を置き換えます。secrets を省いて送ると宣言しておいたシークレット値が削除され、Statement がまだその値を { /secrets/… } で参照していれば保存が拒否されます。そのため、更新するたびに secrets も一緒に送ります。照会レスポンスの値をそのまま送り返せば済みます。
  • 実行中の値: 読んだ値で何をするかは Statement が決めます。読んだ値を Return で返すと実行レスポンスと ScriptLog に残り、SetVar・Cache・Content に入れるとその場所に元の値のまま残ります。シークレット値は、その値を必要とする外部 API にだけ送ります。
  • App Bundle: Script が App Bundle にパッキングされるとき、secrets の value は ****** で隠され、key と description はそのまま含まれます。その App Bundle をインストールして作られた Script はシークレット値が ****** の状態なので、インストールした側で実際の値を入れて初めて、その値を読む Statement が動作します。secrets 以外の場所(Http のヘッダー、Signature の secret など)に書いた値は隠されず、そのまま含まれます。

1 つの Script には secrets を 20 個まで置けます。ポインターの規則は 値式の /secrets で扱います。

実行アイデンティティと認可

  • 実行アイデンティティ: 実行中のすべてのリソース操作は、/execute を呼び出したユーザーのアイデンティティで実行されます。作成または更新されるリソースの createdBy/updatedBy は呼び出し元となり、createdBy: ":self" スコープも呼び出し元を基準に解決されます。例外は匿名呼び出しです。 /execute/anonymous で入ってきた実行には呼び出し元がいないため、どちらも 作成者を基準に解決されます(匿名呼び出し)。
  • 認可の境界は二つであり、ランタイムでは Statement ごとにリソース権限を再検査しません。
    1. 作成時(保存): Script を保存する際に、作成者がそれらの Statement が使う リソースとアクションの権限を実際に持っているかを検査します。一つでも欠けていれば保存が拒否されます。つまり、権限のない操作を含む Script はそもそも保存されません。リソースを選ぶ Statement は、leaf であれブロックを所有する ResourceForEach であれ、すべてこの検査を受けます。すでに保存してある定義も更新するときに再び検査されるため、権限が回収された後はその定義を直して保存できません。
      • 会員ディレクトリ(ServiceUser)は権限マップではなく設定の軸で検査します。 読み取りの 3 つの Statement と ResourceUpdate・ResourcePatch に resource: "ServiceUser" を書くには、作成者の SpaceRole settings に SETTING_SERVICE_LOGIN(または SETTING_ALL)が必要です(SpaceRole の settings)。会員ディレクトリが、他のすべての経路でも Space 設定が管掌するリソースだからです。
      • 会員を作る・消す Statement は、どの役割でも保存できません。 Script は会員を作ったり消したりできないため、権限不足(403)ではなく書き方を誤った Statement(400)として拒否されます。権限を足せば閉じられる隙間ではないという意味です。許される変更は ResourceUpdate・ResourcePatch の roleOverride と enableLogin だけです(会員ディレクトリを扱う)。
    2. 呼び出し時(/execute): 呼び出し元の Script Execute 権限のみを検査します。権限がなければ 403 です。通過すると、Statement ごとのリソース権限はランタイムで再確認せずに実行します。プログラミングにおける関数の実行権限と同じ方式です。関数を実行する権限さえあれば、その中の個々の操作の権限は再び問われません。匿名呼び出しの経路にはこの検査がありません。 検査する呼び出し元がいないからであり、そのためその経路を開くことは、Script 1 つを認証なしで公開することと同じです。
  • 直接呼び出しのブロック(directCallEnabled): Script の directCallEnabled が false の場合、/execute への直接呼び出し自体が拒否されます。このゲートは Execute 権限の検査を通過したあとにかかるため、Execute 権限があってもブロックされます。権限のない呼び出し元は、このゲートに達する前に 403 を受け取ります。このゲートはそのエンドポイントにのみあるので、Webhook の連携アクション(script)と Scheduler はそのまま実行します。デフォルト値は true(直接呼び出し許可)です。
  • 匿名呼び出し(anonymousCallEnabled): デフォルト値は false です。true にすると、その Script だけが認証のない専用経路(/execute/anonymous)でも実行され、そのときの 実行アイデンティティは呼び出し元ではなく作成者です。上の二つの境界のうち呼び出し時の検査(Execute 権限)がその経路にはないため、実質的な認証は Script が自分で行います(受け取ったリクエストの署名検証)。有効にする条件と保存の規則は 匿名呼び出し で扱います。
  • 所有権スコープ: where フィルターの createdBy: ":self" は「現在の呼び出し元が作成したものだけ」を意味します(例: 自分のウォレットのみ照会)。匿名呼び出しを許可した Script では、このフィルターを使えません。呼び出し元がなく作成者に解決されるため、所有権スコープという本来の意味が成り立たないからです。
  • 委任された権限(作成時の注意): 上記の二つの境界を合わせると、Script の実行は 作成者の権限を委任されて行われるのと同じです。呼び出し元は Execute 一つだけあればよく、Script 内の Statement は作成者が保存時に認可された範囲でそのまま実行されます。したがって、呼び出し元が自分自身ではできないリソース操作も Script を通じて起こりえます。作成者に付与された権限がそのままその Script の影響範囲となるため、Script に含める動作は慎重に決めます。

要約チェックリスト

保存前に次を確認します。

  • 匿名呼び出し(anonymousCallEnabled)を有効にしたなら、where に createdBy: ":self" がなく、受け取ったリクエストを検証する Statement(Signature など)を先頭に置いています。
  • 外部呼び出し(Http・EmailSend)の数と全 Statement の数はプランの上限以内で、SetVar は 10 個以下、Cache は 5 個以下です。
  • Cache を使ったなら、key をリテラルで書き、Loop や ResourceForEach の中には置いていません。
  • ResourceForEach で大きな集合を巡回する場合は、limit を宣言するか、完走可能なサイズかを確認しました。
  • 繰り返し(Loop・ResourceForEach)を含めたなら、その繰り返しが掛け算として 時間予算 に入ることを確認しました(外部呼び出しがなければ 30 秒の基本予算が限度です)。
  • 外部 API キーや署名鍵のようなシークレット値は secrets に宣言し、{ /secrets/<key> } で読んでいます。Statement に値をそのまま書いたシークレット値はありません。
  • 全体更新(PUT)で保存するなら、secrets も一緒に送っています。
  • 署名検証に使うメッセージは /payload ではなく { /rawPayload } で取っています。
  • 会員(ServiceUser)を扱う Statement があれば、作成者に SETTING_SERVICE_LOGIN があり、そのリソースを作ったり消したりする Statement は入れていません。
  • 取り消せない操作(外部呼び出し)はできるだけ後ろに置いています。
  • Http でファイルを送るなら、リクエスト本文フィールド(body・urlBody・multipartBody)を 1 つだけ書き、各ファイルが プランごとのダウンロード上限 以内かを確認しました。
  • update/patch の競合が心配なら ResourceUpdate や ResourcePatch の version を使います。
  • 結果を返すには Return.value を明示しています。

エラー

定義の形が静的制約に反して保存が拒否されるときに出るコードです。値式の規則に反したコードは 値式のエラー に、呼び出し・削除のときに出るコードは エンドポイントのエラー にあります。すべてのリソースに共通するコードは 共通エラー を参照してください。

コード条件
WGL400066一つの定義に含めた Cache Statement が 5 個を超えています。
WGL400068Cache Statement を Loop や ResourceForEach のブロック内に置きました。
WGL400067Cache Statement の key に、リテラルではなく { /pointer } 参照を書きました。
WGL400065Cache Statement の ttl が許容範囲を外れています。
WGL400063Cache Statement で action に該当しないフィールドを書きました(Get に ttl、Set に defaultValue)。
WGL400060ResourceCreate・ResourceDelete と公開・アーカイブの Statement の resource に "ServiceUser" を書きました。会員ディレクトリは照会の 3 つの Statement と ResourceUpdate・ResourcePatch だけを受け取ります。
WGL400077ResourceCount の resource に数えられないリソースを書きました。Media と会員ディレクトリ(ServiceUser)は数えられません。
WGL400037EmailSend に to と toServiceUser を一緒に書いたか、両方とも空にしました。ちょうど 1 つだけ書きます。
WGL400054EmailSend の受信者の合計(to 1 名 + cc + bcc)が 50 名を超えました。
WGL400039EmailSend の timeoutMs が上限を超えました。
WGL400101EmailSend に body と templateBody を一緒に書いたか、両方とも空にしました。ちょうど 1 つだけ書きます。
WGL400102EmailSend の templateBody.source が、この Script の ResourceRead・ResourceFind が読んだ Content を指すポインター 1 つではありません。ポインターの前後に他の文字があっても拒否されます。
WGL400061匿名呼び出しを許可した Script(anonymousCallEnabled)で、読み取り Statement の where に createdBy: ":self" を書きました。
WGL400023一つの定義に含めた SetVar Statement が 10 個を超えています。
WGL400026Http Statement の retry が上限の 2 を超えています。
WGL400087Http にリクエスト本文フィールド(body・urlBody・multipartBody)を 2 つ以上書きました。
WGL400088Http の multipartBody に part が 1 つもありません。
WGL400089multipartBody の part に value と url を両方書いたか、どちらも書いていません。
WGL400090multipartBody の part に url なしで fileName を書きました。
WGL400036ResourceForEach が処理できる項目数の上限を超えています。
WGL400094secrets に同じ key を使う項目が 2 つ以上あります。
WGL400095一つの定義に含めた secrets が 20 個を超えています。
WGL400086secrets の value が 1〜4,096 文字の範囲を外れています。エラーには value が含まれません。
WGL400086{ /pointer } を含まない PdfWatermark の text が 1〜64 文字の範囲を外れています。
WGL400096Media インジェスト指示の transformations が配列でないか、要素の type が PdfWatermark でないか、PdfWatermark に text がないかオブジェクト・配列であるか、color が #RRGGBB 形式でないか、書いたとおりの text に使えない文字や改行が含まれています。
WGL429005一つの定義に含めた Statement の総数が料金プランの上限を超えています。
WGL429006一つの定義に含めた外部呼び出し(Http・EmailSend)の数が料金プランの上限を超えています。
WGL403015定義に含めた Statement が扱うリソースとアクションの権限を、作成者が持っていません。権限があっても、その許可に contentType・createdBy・tag フィルターが付いていれば保存が拒否されます。 条件のない許可でなければなりません。唯一の例外は Content の Create で、このときは contentType の範囲を定めた許可も認められ、Statement に書いた contentType と照合します(Media の Create にこの例外はありません)。読み取り Statement の resource に "ServiceUser" を書いたのに、作成者に SETTING_SERVICE_LOGIN がない場合もこのコードです。