@nodegx/mcp 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodegx-mcp-bundles",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "private": true,
5
5
  "description": "Build metadata for the bundled CLIs beside it. See build-cloud-bundle.mjs: @noodl/platform reads it."
6
6
  }
@@ -7119,7 +7119,8 @@
7119
7119
  "isfalse": "Boolean level, inverse of `result`; saves an Inverter when driving 'error shown' style inputs."
7120
7120
  },
7121
7121
  "examples": [
7122
- "validate-before-submit"
7122
+ "validate-before-submit",
7123
+ "score-then-move-on"
7123
7124
  ],
7124
7125
  "patterns": [
7125
7126
  "Button `onClick` → `eval`, with `ontrue` driving the action: gate an action behind a validity check at click time.",
@@ -7128,7 +7129,7 @@
7128
7129
  "antiPatterns": [
7129
7130
  "Wiring `ontrue` (signal) to a boolean input like `visible` delivers only a momentary pulse — use `result` for anything that must stay on.",
7130
7131
  "Leaving Run On Value Change on when `ontrue`/`onfalse` DOES something (advance a question, navigate, set a Variable, start a Timer): the gate then fires whenever its input settles, including once while the page loads, before anyone has acted. Set `runOnChange-condition: false` and wire `eval` from the signal that should ask — a Repeat's tick, a button's click, a Timer's finish.",
7131
- "Two gates evaluated by one signal, where one gate's On True changes what the other one reads (advancing a question index that the other's 'is the answer right?' compares against): the second can read the changed value. Chain them instead — the reader's `done` → the writer's `eval` — so the reader decides first.",
7132
+ "Two gates evaluated by one signal, where one gate's On True changes what the other one reads (advancing a question index that the other's 'is the answer right?' compares against): the reader sees the changed value, whichever order the two are wired in, so wire order is no fix. Chain them instead — the reader's `done` → the writer's `eval` — so the reader decides first (example `score-then-move-on`; the Problems panel warns `condition-reads-a-siblings-change`).",
7132
7133
  "Expecting a second Evaluate with an unchanged condition to stay silent: every Evaluate fires On True or On False again, whether or not the value changed.",
7133
7134
  "A gate left on Run On Value Change fires the moment its condition is true, even for one step in the middle of a chain of Set Variables. A timeout watching 'time is up AND not answered' fires again while moving on if `answered` is cleared while the countdown still reads 0: the next question starts answered and its first tap is refused (a quiz that scored the right answer after a timeout as wrong). Reset the value that makes it true (the countdown back to 10) before the one that holds it off (`answered` back to false)."
7134
7135
  ],
@@ -51302,7 +51303,7 @@
51302
51303
  "always: the size it holds now, a bare number read in the unit it held; drawn at the next paint"
51303
51304
  ],
51304
51305
  "visible": [
51305
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
51306
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
51306
51307
  ]
51307
51308
  },
51308
51309
  "warnings": {
@@ -53520,7 +53521,7 @@
53520
53521
  "always: the page, or the scrolling Group holding it, scrolls until the box can be seen"
53521
53522
  ],
53522
53523
  "visible": [
53523
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
53524
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
53524
53525
  ]
53525
53526
  },
53526
53527
  "warnings": {
@@ -56156,7 +56157,7 @@
56156
56157
  "always: the size it holds now, a bare number read in the unit it held; drawn at the next paint"
56157
56158
  ],
56158
56159
  "visible": [
56159
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
56160
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
56160
56161
  ]
56161
56162
  },
56162
56163
  "warnings": {
@@ -58360,7 +58361,7 @@
58360
58361
  "always: the page, or the scrolling Group holding it, scrolls until the button can be seen"
58361
58362
  ],
58362
58363
  "visible": [
58363
- "always: shown or hidden at the next paint, its space kept; hidden, it takes no click and a Focus does not reach it"
58364
+ "always: shown or hidden at once, its space kept; hidden, it takes no click and a Focus does not reach it"
58364
58365
  ]
58365
58366
  },
58366
58367
  "warnings": {
@@ -60786,7 +60787,7 @@
60786
60787
  "always: the size it holds now, a bare number read in the unit it held; drawn at the next paint"
60787
60788
  ],
60788
60789
  "visible": [
60789
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
60790
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
60790
60791
  ]
60791
60792
  },
60792
60793
  "warnings": {
@@ -63679,7 +63680,7 @@
63679
63680
  "always: the size it holds now, a bare number read in the unit it held; drawn at the next paint"
63680
63681
  ],
63681
63682
  "visible": [
63682
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
63683
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
63683
63684
  ],
63684
63685
  "opacity": [
63685
63686
  "always: how see-through it is; at exactly 0 it takes no pointer, and an act goes to what is behind it"
@@ -69257,7 +69258,7 @@
69257
69258
  },
69258
69259
  "isSignal": false,
69259
69260
  "default": false,
69260
- "description": "Whether a request with no valid session token is allowed to run this function at all"
69261
+ "description": "Whether a request with no valid session token is allowed to run this function at all. A run the app starts itself — a schedule, a row change, a run from Studio — is always allowed and sees nobody signed in; a webhook is a request like any other"
69261
69262
  },
69262
69263
  {
69263
69264
  "name": "params",
@@ -75415,7 +75416,7 @@
75415
75416
  "label": "Update note",
75416
75417
  "parameters": {
75417
75418
  "collectionName": "Note",
75418
- "idSource": "value"
75419
+ "idSource": "explicit"
75419
75420
  }
75420
75421
  },
75421
75422
  {
@@ -75424,7 +75425,7 @@
75424
75425
  "label": "Delete note",
75425
75426
  "parameters": {
75426
75427
  "collectionName": "Note",
75427
- "idSource": "value"
75428
+ "idSource": "explicit"
75428
75429
  }
75429
75430
  }
75430
75431
  ],
@@ -86180,6 +86181,176 @@
86180
86181
  }
86181
86182
  ]
86182
86183
  },
86184
+ {
86185
+ "id": "option-set",
86186
+ "title": "A fixed list as an option set: the languages, read by a dropdown, the choice stored by a Set Variable",
86187
+ "description": "A fixed list (a language, a status, a priority) lives in ONE place: a logic component under `Option sets/<Name>` holding one `Static Data` node with the list as a JSON array, published through `Component Outputs` as `items` and `count`. NodeGX Studio lists every component under `Option sets/` in Data → Option sets, where the person adds or renames an option themselves, and the NodeGX editor shows it as the Static Data node it is. A page places an instance and wires its `items` wherever the list is needed (a Dropdown here; a `For Each` of buttons works the same). The step that stores the person's choice takes the chosen row's value from the control, so no literal like \"fr\" or \"en\" is typed into a Set Variable anywhere: two steps typing two literals into one variable are a fixed list the project does not have, and the next language means editing every one of them. Each row carries `Label` (what the person reads) and `Value` (what the app stores), the two fields a Dropdown reads off each item.",
86188
+ "demonstrates": [
86189
+ "Static Data",
86190
+ "Component Outputs",
86191
+ "net.noodl.controls.options",
86192
+ "Set Variable",
86193
+ "Variable2"
86194
+ ],
86195
+ "components": [
86196
+ {
86197
+ "name": "/Option sets/Languages",
86198
+ "nodes": [
86199
+ {
86200
+ "id": "options",
86201
+ "type": "Static Data",
86202
+ "label": "Languages · the options",
86203
+ "parameters": {
86204
+ "type": "json",
86205
+ "json": "[{\"Label\":\"English\",\"Value\":\"en\"},{\"Label\":\"Français\",\"Value\":\"fr\"}]"
86206
+ }
86207
+ },
86208
+ {
86209
+ "id": "out",
86210
+ "type": "Component Outputs",
86211
+ "label": "What the page reads",
86212
+ "ports": [
86213
+ {
86214
+ "name": "items",
86215
+ "plug": "input",
86216
+ "type": "array"
86217
+ },
86218
+ {
86219
+ "name": "count",
86220
+ "plug": "input",
86221
+ "type": "number"
86222
+ }
86223
+ ]
86224
+ }
86225
+ ],
86226
+ "connections": [
86227
+ {
86228
+ "fromId": "options",
86229
+ "fromProperty": "items",
86230
+ "toId": "out",
86231
+ "toProperty": "items"
86232
+ },
86233
+ {
86234
+ "fromId": "options",
86235
+ "fromProperty": "count",
86236
+ "toId": "out",
86237
+ "toProperty": "count"
86238
+ }
86239
+ ]
86240
+ },
86241
+ {
86242
+ "name": "/Pages/Language",
86243
+ "nodes": [
86244
+ {
86245
+ "id": "page",
86246
+ "type": "Page",
86247
+ "label": "Page",
86248
+ "parameters": {
86249
+ "title": "Language",
86250
+ "urlPath": "language"
86251
+ },
86252
+ "children": [
86253
+ "body"
86254
+ ]
86255
+ },
86256
+ {
86257
+ "id": "body",
86258
+ "type": "Group",
86259
+ "label": "Body",
86260
+ "parent": "page",
86261
+ "parameters": {
86262
+ "width": {
86263
+ "value": 100,
86264
+ "unit": "%"
86265
+ },
86266
+ "sizeMode": "contentHeight",
86267
+ "flexDirection": "column",
86268
+ "rowGap": "var(--space-3)",
86269
+ "paddingLeft": "var(--space-4)",
86270
+ "paddingRight": "var(--space-4)",
86271
+ "paddingTop": "var(--space-4)",
86272
+ "paddingBottom": "var(--space-4)"
86273
+ },
86274
+ "children": [
86275
+ "prompt",
86276
+ "picker"
86277
+ ]
86278
+ },
86279
+ {
86280
+ "id": "prompt",
86281
+ "type": "Text",
86282
+ "label": "Prompt",
86283
+ "parent": "body",
86284
+ "parameters": {
86285
+ "text": "Language"
86286
+ }
86287
+ },
86288
+ {
86289
+ "id": "picker",
86290
+ "type": "net.noodl.controls.options",
86291
+ "label": "Language picker",
86292
+ "parent": "body",
86293
+ "parameters": {
86294
+ "placeholder": "Choose a language",
86295
+ "sizeMode": "contentHeight",
86296
+ "width": {
86297
+ "value": 100,
86298
+ "unit": "%"
86299
+ }
86300
+ }
86301
+ },
86302
+ {
86303
+ "id": "languages",
86304
+ "type": "/Option sets/Languages",
86305
+ "label": "Languages"
86306
+ },
86307
+ {
86308
+ "id": "store_language",
86309
+ "type": "Set Variable",
86310
+ "label": "Remember the language",
86311
+ "parameters": {
86312
+ "name": "language",
86313
+ "setWith": "string"
86314
+ }
86315
+ },
86316
+ {
86317
+ "id": "read_language",
86318
+ "type": "Variable2",
86319
+ "label": "Current language",
86320
+ "parameters": {
86321
+ "name": "language"
86322
+ }
86323
+ }
86324
+ ],
86325
+ "connections": [
86326
+ {
86327
+ "fromId": "languages",
86328
+ "fromProperty": "items",
86329
+ "toId": "picker",
86330
+ "toProperty": "items"
86331
+ },
86332
+ {
86333
+ "fromId": "picker",
86334
+ "fromProperty": "value",
86335
+ "toId": "store_language",
86336
+ "toProperty": "value"
86337
+ },
86338
+ {
86339
+ "fromId": "picker",
86340
+ "fromProperty": "onChange",
86341
+ "toId": "store_language",
86342
+ "toProperty": "do"
86343
+ },
86344
+ {
86345
+ "fromId": "read_language",
86346
+ "fromProperty": "value",
86347
+ "toId": "picker",
86348
+ "toProperty": "value"
86349
+ }
86350
+ ]
86351
+ }
86352
+ ]
86353
+ },
86183
86354
  {
86184
86355
  "id": "repeater-query-records",
86185
86356
  "title": "List page: Repeater fed by Query Records",
@@ -86294,6 +86465,158 @@
86294
86465
  }
86295
86466
  ]
86296
86467
  },
86468
+ {
86469
+ "id": "score-then-move-on",
86470
+ "title": "Score an answer, then move on to the next question",
86471
+ "description": "Two gates that act on one press, where the second changes what the first reads: moving on changes the question index, and the 'is the answer right?' check compares against that index. Wire both Evaluates from the press and the scoring gate reads the NEXT question, whichever order the wires are in, so every answer is scored against the wrong question. Chain them instead: the press evaluates the scoring gate, and the scoring gate's Done evaluates the move-on gate, so the score is decided before the index moves. Both gates have Run On Value Change unticked, so only the press asks them.",
86472
+ "demonstrates": [
86473
+ "Condition",
86474
+ "Counter",
86475
+ "Expression",
86476
+ "net.noodl.controls.button",
86477
+ "net.noodl.controls.textinput",
86478
+ "Group"
86479
+ ],
86480
+ "components": [
86481
+ {
86482
+ "name": "/Quiz Step",
86483
+ "nodes": [
86484
+ {
86485
+ "id": "root",
86486
+ "type": "Group",
86487
+ "label": "Question layout",
86488
+ "parameters": {
86489
+ "flexDirection": "column",
86490
+ "paddingLeft": "var(--space-4)",
86491
+ "paddingRight": "var(--space-4)",
86492
+ "paddingTop": "var(--space-4)",
86493
+ "paddingBottom": "var(--space-4)"
86494
+ },
86495
+ "children": [
86496
+ "answer_input",
86497
+ "next_button"
86498
+ ]
86499
+ },
86500
+ {
86501
+ "id": "answer_input",
86502
+ "type": "net.noodl.controls.textinput",
86503
+ "label": "Answer field",
86504
+ "parent": "root",
86505
+ "parameters": {
86506
+ "placeholder": "Your answer"
86507
+ }
86508
+ },
86509
+ {
86510
+ "id": "next_button",
86511
+ "type": "net.noodl.controls.button",
86512
+ "label": "Next",
86513
+ "parent": "root",
86514
+ "parameters": {
86515
+ "label": "Next"
86516
+ }
86517
+ },
86518
+ {
86519
+ "id": "question_index",
86520
+ "type": "Counter",
86521
+ "label": "Question index"
86522
+ },
86523
+ {
86524
+ "id": "score",
86525
+ "type": "Counter",
86526
+ "label": "Score"
86527
+ },
86528
+ {
86529
+ "id": "is_right",
86530
+ "type": "Expression",
86531
+ "label": "Answer is right?",
86532
+ "parameters": {
86533
+ "expression": "answer == ['Paris', 'Lisbon', 'Rome', 'Madrid', 'Berlin'][index]"
86534
+ }
86535
+ },
86536
+ {
86537
+ "id": "is_not_last",
86538
+ "type": "Expression",
86539
+ "label": "Not the last question?",
86540
+ "parameters": {
86541
+ "expression": "index < 4"
86542
+ }
86543
+ },
86544
+ {
86545
+ "id": "score_gate",
86546
+ "type": "Condition",
86547
+ "label": "Score if right",
86548
+ "parameters": {
86549
+ "runOnChange-condition": false
86550
+ }
86551
+ },
86552
+ {
86553
+ "id": "advance_gate",
86554
+ "type": "Condition",
86555
+ "label": "Move on if not last",
86556
+ "parameters": {
86557
+ "runOnChange-condition": false
86558
+ }
86559
+ }
86560
+ ],
86561
+ "connections": [
86562
+ {
86563
+ "fromId": "answer_input",
86564
+ "fromProperty": "onTextChanged",
86565
+ "toId": "is_right",
86566
+ "toProperty": "answer"
86567
+ },
86568
+ {
86569
+ "fromId": "question_index",
86570
+ "fromProperty": "currentCount",
86571
+ "toId": "is_right",
86572
+ "toProperty": "index"
86573
+ },
86574
+ {
86575
+ "fromId": "question_index",
86576
+ "fromProperty": "currentCount",
86577
+ "toId": "is_not_last",
86578
+ "toProperty": "index"
86579
+ },
86580
+ {
86581
+ "fromId": "is_right",
86582
+ "fromProperty": "result",
86583
+ "toId": "score_gate",
86584
+ "toProperty": "condition"
86585
+ },
86586
+ {
86587
+ "fromId": "is_not_last",
86588
+ "fromProperty": "result",
86589
+ "toId": "advance_gate",
86590
+ "toProperty": "condition"
86591
+ },
86592
+ {
86593
+ "fromId": "next_button",
86594
+ "fromProperty": "onClick",
86595
+ "toId": "score_gate",
86596
+ "toProperty": "eval"
86597
+ },
86598
+ {
86599
+ "fromId": "score_gate",
86600
+ "fromProperty": "ontrue",
86601
+ "toId": "score",
86602
+ "toProperty": "increase"
86603
+ },
86604
+ {
86605
+ "fromId": "score_gate",
86606
+ "fromProperty": "done",
86607
+ "toId": "advance_gate",
86608
+ "toProperty": "eval"
86609
+ },
86610
+ {
86611
+ "fromId": "advance_gate",
86612
+ "fromProperty": "ontrue",
86613
+ "toId": "question_index",
86614
+ "toProperty": "increase"
86615
+ }
86616
+ ]
86617
+ }
86618
+ ]
86619
+ },
86297
86620
  {
86298
86621
  "id": "send-event-across-components",
86299
86622
  "title": "Decoupled communication with Send Event / Receive Event",
@@ -87500,7 +87823,7 @@
87500
87823
  {
87501
87824
  "id": "ui-empty-state",
87502
87825
  "title": "Empty state: what a list shows when it has no rows",
87503
- "description": "A list with nothing in it should say what it is and what to do, not render nothing. The designed version is small and centred inside a dashed card: an icon in a muted disc, one heading, one line of explanation capped at ~380px, and exactly one action. The switch is one wire: the query's `isEmpty` boolean into the empty state's `mounted` input. Use `mounted`, not `visible` — `mounted` takes the element out of the layout, while `visible` only hides it and keeps the space it occupies, which leaves a page-height hole above your empty state. The list needs no gate at all: a `For Each` over an empty array renders no rows and occupies no height, so nothing has to be inverted and no logic node is involved. Skipping the empty state is the difference between an app that looks unfinished on first run and one that does not, and first run is when it is always seen.",
87826
+ "description": "A list with nothing in it should say what it is and what to do, not render nothing. The designed version is small and centred inside a dashed card: an icon in a muted disc, one heading, one line of explanation capped at ~380px, and exactly one action. The switch is one wire: the query's `isEmpty` boolean into the `mounted` input of a Group that holds the empty state. A placed component has no `mounted` or `visible` of its own, so the wire goes to the Group around it. Use `mounted`, not `visible` — `mounted` takes the element out of the layout, while `visible` only hides it and keeps the space it occupies, which leaves a page-height hole above your empty state. The list needs no gate at all: a `For Each` over an empty array renders no rows and occupies no height, so nothing has to be inverted and no logic node is involved. Skipping the empty state is the difference between an app that looks unfinished on first run and one that does not, and first run is when it is always seen.",
87504
87827
  "demonstrates": [
87505
87828
  "Group",
87506
87829
  "net.noodl.visual.icon",
@@ -87567,7 +87890,7 @@
87567
87890
  "children": [
87568
87891
  "heading",
87569
87892
  "list",
87570
- "empty"
87893
+ "emptyWrap"
87571
87894
  ]
87572
87895
  },
87573
87896
  {
@@ -87591,11 +87914,27 @@
87591
87914
  },
87592
87915
  "parent": "shell"
87593
87916
  },
87917
+ {
87918
+ "id": "emptyWrap",
87919
+ "type": "Group",
87920
+ "label": "Shown only when the query is empty",
87921
+ "parameters": {
87922
+ "width": {
87923
+ "value": 100,
87924
+ "unit": "%"
87925
+ },
87926
+ "flexDirection": "column"
87927
+ },
87928
+ "parent": "shell",
87929
+ "children": [
87930
+ "empty"
87931
+ ]
87932
+ },
87594
87933
  {
87595
87934
  "id": "empty",
87596
87935
  "type": "/Components/EmptyState",
87597
- "label": "Shown only when the query is empty",
87598
- "parent": "shell"
87936
+ "label": "The empty state",
87937
+ "parent": "emptyWrap"
87599
87938
  },
87600
87939
  {
87601
87940
  "id": "query",
@@ -87616,7 +87955,7 @@
87616
87955
  {
87617
87956
  "fromId": "query",
87618
87957
  "fromProperty": "isEmpty",
87619
- "toId": "empty",
87958
+ "toId": "emptyWrap",
87620
87959
  "toProperty": "mounted"
87621
87960
  }
87622
87961
  ]
@@ -47268,7 +47268,7 @@
47268
47268
  "always: the size it holds now, a bare number read in the unit it held; drawn at the next paint"
47269
47269
  ],
47270
47270
  "visible": [
47271
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
47271
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
47272
47272
  ]
47273
47273
  },
47274
47274
  "warnings": {
@@ -49453,7 +49453,7 @@
49453
49453
  "always: the page, or the scrolling Group holding it, scrolls until the box can be seen"
49454
49454
  ],
49455
49455
  "visible": [
49456
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
49456
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
49457
49457
  ]
49458
49458
  },
49459
49459
  "warnings": {
@@ -52065,7 +52065,7 @@
52065
52065
  "always: the size it holds now, a bare number read in the unit it held; drawn at the next paint"
52066
52066
  ],
52067
52067
  "visible": [
52068
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
52068
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
52069
52069
  ]
52070
52070
  },
52071
52071
  "warnings": {
@@ -54247,7 +54247,7 @@
54247
54247
  "always: the page, or the scrolling Group holding it, scrolls until the button can be seen"
54248
54248
  ],
54249
54249
  "visible": [
54250
- "always: shown or hidden at the next paint, its space kept; hidden, it takes no click and a Focus does not reach it"
54250
+ "always: shown or hidden at once, its space kept; hidden, it takes no click and a Focus does not reach it"
54251
54251
  ]
54252
54252
  },
54253
54253
  "warnings": {
@@ -56652,7 +56652,7 @@
56652
56652
  "always: the size it holds now, a bare number read in the unit it held; drawn at the next paint"
56653
56653
  ],
56654
56654
  "visible": [
56655
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
56655
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
56656
56656
  ]
56657
56657
  },
56658
56658
  "warnings": {
@@ -59522,7 +59522,7 @@
59522
59522
  "always: the size it holds now, a bare number read in the unit it held; drawn at the next paint"
59523
59523
  ],
59524
59524
  "visible": [
59525
- "always: shown or hidden at the next paint, its space kept; hidden, a Focus does not reach it"
59525
+ "always: shown or hidden at once, its space kept; hidden, a Focus does not reach it"
59526
59526
  ],
59527
59527
  "opacity": [
59528
59528
  "always: how see-through it is; at exactly 0 it takes no pointer, and an act goes to what is behind it"
@@ -64364,7 +64364,7 @@
64364
64364
  },
64365
64365
  "isSignal": false,
64366
64366
  "default": false,
64367
- "description": "Whether a request with no valid session token is allowed to run this function at all"
64367
+ "description": "Whether a request with no valid session token is allowed to run this function at all. A run the app starts itself — a schedule, a row change, a run from Studio — is always allowed and sees nobody signed in; a webhook is a request like any other"
64368
64368
  },
64369
64369
  {
64370
64370
  "name": "params",