Changeset

6245:ea58d2893afb draft default tip

Merge update
author Trần H. Trung <xmpp:trần.h.trung@trung.fun>
date Tue, 29 Apr 2025 23:27:06 +0700
parents 6232:d72010642b31 (current diff) 6244:c71d8bc77c95 (diff)
children
files mod_http_oauth2/README.md mod_http_oauth2/mod_http_oauth2.lua mod_invites_page/mod_invites_page.lua
diffstat 10 files changed, 720 insertions(+), 283 deletions(-) [+]
line wrap: on
line diff
--- a/misc/grafana/prosody-dashboard.json	Fri Apr 11 23:19:21 2025 +0700
+++ b/misc/grafana/prosody-dashboard.json	Tue Apr 29 23:27:06 2025 +0700
@@ -1,11 +1,9 @@
 {
-   "description" : "",
    "editable" : true,
    "fiscalYearStartMonth" : 0,
    "graphTooltip" : 1,
    "id" : 1,
    "links" : [],
-   "liveNow" : false,
    "panels" : [
       {
          "collapsed" : false,
@@ -21,6 +19,7 @@
          "type" : "row"
       },
       {
+         "description" : "This panel requires [mod_measure_process](https://modules.prosody.im/mod_measure_process.html)",
          "fieldConfig" : {
             "defaults" : {
                "color" : {
@@ -34,6 +33,7 @@
                   "axisLabel" : "",
                   "axisPlacement" : "right",
                   "barAlignment" : 0,
+                  "barWidthFactor" : 0.6,
                   "drawStyle" : "line",
                   "fillOpacity" : 10,
                   "gradientMode" : "scheme",
@@ -68,8 +68,7 @@
                   "mode" : "absolute",
                   "steps" : [
                      {
-                        "color" : "green",
-                        "value" : null
+                        "color" : "green"
                      },
                      {
                         "color" : "red",
@@ -96,26 +95,33 @@
                "showLegend" : true
             },
             "tooltip" : {
+               "hideZeros" : false,
                "mode" : "single",
                "sort" : "none"
             }
          },
-         "pluginVersion" : "8.2.5",
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
+               "disableTextWrap" : false,
+               "editorMode" : "builder",
                "exemplar" : true,
-               "expr" : "rate(process_cpu_seconds_total{job=\"prosody\"}[$__interval])",
+               "expr" : "rate(process_cpu_seconds_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])",
+               "fullMetaSearch" : false,
+               "includeNullMetadata" : true,
                "instant" : false,
                "interval" : "",
                "intervalFactor" : 2,
                "legendFormat" : "usage",
-               "refId" : "A"
+               "refId" : "A",
+               "useBackend" : false
             }
          ],
          "title" : "CPU",
          "type" : "timeseries"
       },
       {
+         "description" : "This panel requires [mod_measure_lua](https://modules.prosody.im/mod_measure_lua.html), [mod_measure_malloc](https://modules.prosody.im/mod_measure_malloc.html), and [mod_measure_process](https://modules.prosody.im/mod_measure_process.html),",
          "fieldConfig" : {
             "defaults" : {
                "color" : {
@@ -128,6 +134,7 @@
                   "axisLabel" : "",
                   "axisPlacement" : "right",
                   "barAlignment" : 0,
+                  "barWidthFactor" : 0.6,
                   "drawStyle" : "line",
                   "fillOpacity" : 10,
                   "gradientMode" : "none",
@@ -162,8 +169,7 @@
                   "mode" : "percentage",
                   "steps" : [
                      {
-                        "color" : "green",
-                        "value" : null
+                        "color" : "green"
                      }
                   ]
                },
@@ -177,9 +183,9 @@
                      "options" : {
                         "mode" : "exclude",
                         "names" : [
+                           "Lua",
                            "RSS",
-                           "Used",
-                           "Lua"
+                           "Used"
                         ],
                         "prefix" : "All except:",
                         "readOnly" : true
@@ -213,60 +219,79 @@
                "showLegend" : true
             },
             "tooltip" : {
+               "hideZeros" : false,
                "mode" : "single",
                "sort" : "none"
             }
          },
-         "pluginVersion" : "8.2.5",
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
+               "disableTextWrap" : false,
+               "editorMode" : "code",
                "exemplar" : true,
-               "expr" : "max_over_time(process_virtual_memory_bytes{job=\"prosody\"}[$__interval])",
+               "expr" : "max_over_time(process_virtual_memory_bytes{job=~\"$job\",instance=~\"$instance\"}[$__interval])",
                "fullMetaSearch" : false,
                "hide" : false,
+               "includeNullMetadata" : true,
                "interval" : "",
                "intervalFactor" : 1,
                "legendFormat" : "Virtual",
-               "refId" : "VIRT"
+               "range" : true,
+               "refId" : "VIRT",
+               "useBackend" : false
             },
             {
                "exemplar" : false,
-               "expr" : "max_over_time(process_resident_memory_bytes{job=\"prosody\"}[$__interval])",
+               "expr" : "max_over_time(process_resident_memory_bytes{job=~\"$job\",instance=~\"$instance\"}[$__interval])",
                "interval" : "",
                "legendFormat" : "RSS",
                "refId" : "RSS"
             },
             {
                "exemplar" : false,
-               "expr" : "max_over_time(malloc_heap_allocated_bytes{job=\"prosody\"}[$__interval])",
+               "expr" : "max_over_time(malloc_heap_allocated_bytes{job=~\"$job\",instance=~\"$instance\"}[$__interval])",
                "hide" : false,
                "interval" : "",
                "legendFormat" : "Allocated ({{mode}})",
                "refId" : "Malloc allocated"
             },
             {
+               "editorMode" : "code",
                "exemplar" : false,
-               "expr" : "max_over_time(malloc_heap_used_bytes{job=\"prosody\"}[$__interval])",
+               "expr" : "max_over_time(malloc_heap_used_bytes{job=~\"$job\",instance=~\"$instance\"}[$__interval])",
                "hide" : false,
                "interval" : "",
                "legendFormat" : "Used",
+               "range" : true,
                "refId" : "Malloc Used"
             },
             {
+               "editorMode" : "code",
                "exemplar" : false,
-               "expr" : "max_over_time(lua_heap_bytes{job=\"prosody\"}[$__interval])",
+               "expr" : "max_over_time(lua_heap_bytes{job=~\"$job\",instance=~\"$instance\"}[$__interval])",
                "hide" : false,
                "interval" : "",
                "legendFormat" : "Lua",
+               "range" : true,
                "refId" : "Lua"
             },
             {
                "exemplar" : false,
-               "expr" : "sum(lua_heap_bytes{job=\"prosody\"}) / (sum(prosody_mod_c2s__connections{job=\"prosody\"})+sum(prosody_mod_s2s__connections_inbound{job=\"prosody\"})+sum(prosody_mod_s2s__connections_outbound{job=\"prosody\"}))",
+               "expr" : "sum(lua_heap_bytes{job=~\"$job\",instance=~\"$instance\"}) / (\nsum(prosody_mod_c2s__connections{job=~\"$job\",instance=~\"$instance\"}) +\nsum(prosody_mod_s2s__connections_inbound{job=~\"$job\",instance=~\"$instance\"}) +\nsum(prosody_mod_s2s__connections_outbound{job=~\"$job\",instance=~\"$instance\"})\n)",
                "hide" : false,
                "interval" : "",
                "legendFormat" : "Lua (per connection)",
                "refId" : "LuaPerConn"
+            },
+            {
+               "editorMode" : "code",
+               "expr" : "max_over_time(malloc_heap_unused_bytes{job=~\"$job\",instance=~\"$instance\"}[$__interval])",
+               "hide" : false,
+               "instant" : false,
+               "legendFormat" : "Unused",
+               "range" : true,
+               "refId" : "A"
             }
          ],
          "title" : "Memory",
@@ -298,6 +323,7 @@
                   "axisLabel" : "",
                   "axisPlacement" : "right",
                   "barAlignment" : 0,
+                  "barWidthFactor" : 0.6,
                   "drawStyle" : "line",
                   "fillOpacity" : 100,
                   "gradientMode" : "none",
@@ -329,8 +355,7 @@
                   "mode" : "absolute",
                   "steps" : [
                      {
-                        "color" : "green",
-                        "value" : null
+                        "color" : "green"
                      },
                      {
                         "color" : "red",
@@ -357,14 +382,16 @@
                "showLegend" : true
             },
             "tooltip" : {
+               "hideZeros" : false,
                "mode" : "single",
                "sort" : "none"
             }
          },
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
                "exemplar" : true,
-               "expr" : "prosody_mod_c2s__connections{type=\"c2s\"}",
+               "expr" : "prosody_mod_c2s__connections{job=~\"$job\",instance=~\"$instance\",type=\"c2s\"}",
                "interval" : "",
                "legendFormat" : "{{ip_family}} {{type}}",
                "refId" : "c2s"
@@ -386,6 +413,7 @@
                   "axisLabel" : "",
                   "axisPlacement" : "right",
                   "barAlignment" : 0,
+                  "barWidthFactor" : 0.6,
                   "drawStyle" : "line",
                   "fillOpacity" : 100,
                   "gradientMode" : "none",
@@ -417,8 +445,7 @@
                   "mode" : "absolute",
                   "steps" : [
                      {
-                        "color" : "green",
-                        "value" : null
+                        "color" : "green"
                      },
                      {
                         "color" : "red",
@@ -445,21 +472,23 @@
                "showLegend" : true
             },
             "tooltip" : {
+               "hideZeros" : false,
                "mode" : "single",
                "sort" : "none"
             }
          },
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
                "exemplar" : true,
-               "expr" : "sum(prosody_mod_s2s__connections_inbound{type=\"s2sin\"}) by (ip_family)",
+               "expr" : "sum(prosody_mod_s2s__connections_inbound{job=~\"$job\",instance=~\"$instance\",type=\"s2sin\"}) by (ip_family)",
                "interval" : "",
                "legendFormat" : "{{ip_family}} s2sin",
                "refId" : "s2sin"
             },
             {
                "exemplar" : true,
-               "expr" : "sum(prosody_mod_s2s__connections_outbound{type=\"s2sout\"}) by (ip_family)",
+               "expr" : "sum(prosody_mod_s2s__connections_outbound{job=~\"$job\",instance=~\"$instance\",type=\"s2sout\"}) by (ip_family)",
                "hide" : false,
                "interval" : "",
                "legendFormat" : "{{ip_family}} s2sout",
@@ -517,7 +546,8 @@
                "layout" : "auto"
             },
             "tooltip" : {
-               "show" : true,
+               "mode" : "single",
+               "showColorScale" : false,
                "yHistogram" : false
             },
             "yAxis" : {
@@ -525,13 +555,13 @@
                "reverse" : false
             }
          },
-         "pluginVersion" : "10.2.2",
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
                "disableTextWrap" : false,
                "editorMode" : "builder",
                "exemplar" : false,
-               "expr" : "changes(prosody_mod_c2s__encrypted_total[$__interval])",
+               "expr" : "changes(prosody_mod_c2s__encrypted_total{job=~\"$job\",instance=~\"$instance\"}[$__interval])",
                "fullMetaSearch" : false,
                "includeNullMetadata" : true,
                "interval" : "10m",
@@ -592,7 +622,8 @@
                "layout" : "auto"
             },
             "tooltip" : {
-               "show" : true,
+               "mode" : "single",
+               "showColorScale" : false,
                "yHistogram" : false
             },
             "yAxis" : {
@@ -600,13 +631,13 @@
                "reverse" : false
             }
          },
-         "pluginVersion" : "10.2.2",
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
                "disableTextWrap" : false,
                "editorMode" : "builder",
                "exemplar" : false,
-               "expr" : "changes(prosody_mod_s2s__encrypted_total[$__interval])",
+               "expr" : "changes(prosody_mod_s2s__encrypted_total{job=~\"$job\",instance=~\"$instance\"}[$__interval])",
                "format" : "time_series",
                "fullMetaSearch" : false,
                "includeNullMetadata" : true,
@@ -635,15 +666,6 @@
          "type" : "row"
       },
       {
-         "cards" : {},
-         "color" : {
-            "cardColor" : "#b4ff00",
-            "colorScale" : "sqrt",
-            "colorScheme" : "interpolateRdYlGn",
-            "exponent" : 0.5,
-            "mode" : "spectrum"
-         },
-         "dataFormat" : "tsbuckets",
          "description" : "How long a session has been hibernating when a client resumes it",
          "fieldConfig" : {
             "defaults" : {
@@ -666,13 +688,7 @@
             "x" : 0,
             "y" : 27
          },
-         "heatmap" : {},
-         "hideZeroBuckets" : true,
-         "highlightCards" : true,
          "id" : 14,
-         "legend" : {
-            "show" : true
-         },
          "options" : {
             "calculate" : false,
             "calculation" : {},
@@ -701,7 +717,8 @@
             },
             "showValue" : "never",
             "tooltip" : {
-               "show" : true,
+               "mode" : "single",
+               "showColorScale" : false,
                "yHistogram" : false
             },
             "yAxis" : {
@@ -711,18 +728,17 @@
                "unit" : "clocks"
             }
          },
-         "pluginVersion" : "10.2.2",
-         "reverseYBuckets" : false,
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
                "disableTextWrap" : false,
                "editorMode" : "builder",
                "exemplar" : true,
-               "expr" : "sum by(le) (changes(prosody_mod_smacks__resumption_age_seconds_bucket{host=\"$virtualhost\"}[$__interval]))",
+               "expr" : "rate(prosody_mod_smacks__resumption_age_seconds_bucket{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[$__rate_interval])",
                "format" : "heatmap",
                "fullMetaSearch" : false,
-               "includeNullMetadata" : true,
-               "interval" : "600",
+               "includeNullMetadata" : false,
+               "interval" : "",
                "legendFormat" : "{{le}}",
                "range" : true,
                "refId" : "A",
@@ -730,20 +746,7 @@
             }
          ],
          "title" : "Resumption Age",
-         "tooltip" : {
-            "show" : true,
-            "showHistogram" : false
-         },
-         "type" : "heatmap",
-         "xAxis" : {
-            "show" : true
-         },
-         "yAxis" : {
-            "format" : "clocks",
-            "logBase" : 1,
-            "show" : true
-         },
-         "yBucketBound" : "upper"
+         "type" : "heatmap"
       },
       {
          "fieldConfig" : {
@@ -758,6 +761,7 @@
                   "axisLabel" : "",
                   "axisPlacement" : "auto",
                   "barAlignment" : 0,
+                  "barWidthFactor" : 0.6,
                   "drawStyle" : "line",
                   "fillOpacity" : 0,
                   "gradientMode" : "none",
@@ -788,118 +792,6 @@
                   "mode" : "absolute",
                   "steps" : [
                      {
-                        "color" : "green",
-                        "value" : null
-                     },
-                     {
-                        "color" : "red",
-                        "value" : 80
-                     }
-                  ]
-               },
-               "unit" : "pps"
-            },
-            "overrides" : []
-         },
-         "gridPos" : {
-            "h" : 8,
-            "w" : 12,
-            "x" : 12,
-            "y" : 27
-         },
-         "id" : 16,
-         "options" : {
-            "legend" : {
-               "calcs" : [],
-               "displayMode" : "list",
-               "placement" : "bottom",
-               "showLegend" : true
-            },
-            "tooltip" : {
-               "mode" : "single",
-               "sort" : "none"
-            }
-         },
-         "targets" : [
-            {
-               "editorMode" : "code",
-               "exemplar" : true,
-               "expr" : "rate(prosody_mod_smacks__tx_queued_stanzas_total{host=\"$virtualhost\"}[$__interval])",
-               "interval" : "600",
-               "legendFormat" : "queued on {{host}}",
-               "range" : true,
-               "refId" : "A"
-            },
-            {
-               "editorMode" : "builder",
-               "exemplar" : true,
-               "expr" : "rate(prosody_mod_smacks__tx_acked_stanzas_count{host=\"$virtualhost\"}[$__interval])",
-               "hide" : false,
-               "interval" : "600",
-               "legendFormat" : "acked on {{host}}",
-               "range" : true,
-               "refId" : "B"
-            }
-         ],
-         "title" : "Stanzas",
-         "type" : "timeseries"
-      },
-      {
-         "collapsed" : false,
-         "gridPos" : {
-            "h" : 1,
-            "w" : 24,
-            "x" : 0,
-            "y" : 35
-         },
-         "id" : 28,
-         "panels" : [],
-         "title" : "Mobile optimizations",
-         "type" : "row"
-      },
-      {
-         "fieldConfig" : {
-            "defaults" : {
-               "color" : {
-                  "mode" : "palette-classic"
-               },
-               "custom" : {
-                  "axisBorderShow" : false,
-                  "axisCenteredZero" : false,
-                  "axisColorMode" : "text",
-                  "axisLabel" : "",
-                  "axisPlacement" : "auto",
-                  "barAlignment" : 0,
-                  "drawStyle" : "points",
-                  "fillOpacity" : 0,
-                  "gradientMode" : "none",
-                  "hideFrom" : {
-                     "legend" : false,
-                     "tooltip" : false,
-                     "viz" : false
-                  },
-                  "insertNulls" : false,
-                  "lineInterpolation" : "linear",
-                  "lineWidth" : 1,
-                  "pointSize" : 5,
-                  "scaleDistribution" : {
-                     "type" : "linear"
-                  },
-                  "showPoints" : "auto",
-                  "spanNulls" : false,
-                  "stacking" : {
-                     "group" : "A",
-                     "mode" : "none"
-                  },
-                  "thresholdsStyle" : {
-                     "mode" : "off"
-                  }
-               },
-               "mappings" : [],
-               "thresholds" : {
-                  "mode" : "absolute",
-                  "steps" : [
-                     {
                         "color" : "green"
                      },
                      {
@@ -908,7 +800,89 @@
                      }
                   ]
                },
-               "unit" : "s"
+               "unit" : "pps"
+            },
+            "overrides" : []
+         },
+         "gridPos" : {
+            "h" : 8,
+            "w" : 12,
+            "x" : 12,
+            "y" : 27
+         },
+         "id" : 16,
+         "options" : {
+            "legend" : {
+               "calcs" : [],
+               "displayMode" : "list",
+               "placement" : "bottom",
+               "showLegend" : true
+            },
+            "tooltip" : {
+               "hideZeros" : false,
+               "mode" : "single",
+               "sort" : "none"
+            }
+         },
+         "pluginVersion" : "11.6.0",
+         "targets" : [
+            {
+               "disableTextWrap" : false,
+               "editorMode" : "builder",
+               "exemplar" : true,
+               "expr" : "rate(prosody_mod_smacks__tx_queued_stanzas_total{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[$__interval])",
+               "fullMetaSearch" : false,
+               "includeNullMetadata" : true,
+               "interval" : "600",
+               "legendFormat" : "queued on {{host}}",
+               "range" : true,
+               "refId" : "A",
+               "useBackend" : false
+            },
+            {
+               "disableTextWrap" : false,
+               "editorMode" : "builder",
+               "exemplar" : true,
+               "expr" : "rate(prosody_mod_smacks__tx_acked_stanzas_count{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[$__interval])",
+               "fullMetaSearch" : false,
+               "hide" : false,
+               "includeNullMetadata" : true,
+               "interval" : "600",
+               "legendFormat" : "acked on {{host}}",
+               "range" : true,
+               "refId" : "B",
+               "useBackend" : false
+            }
+         ],
+         "title" : "Stanzas",
+         "type" : "timeseries"
+      },
+      {
+         "collapsed" : false,
+         "gridPos" : {
+            "h" : 1,
+            "w" : 24,
+            "x" : 0,
+            "y" : 35
+         },
+         "id" : 28,
+         "panels" : [],
+         "title" : "Mobile optimizations",
+         "type" : "row"
+      },
+      {
+         "fieldConfig" : {
+            "defaults" : {
+               "custom" : {
+                  "hideFrom" : {
+                     "legend" : false,
+                     "tooltip" : false,
+                     "viz" : false
+                  },
+                  "scaleDistribution" : {
+                     "type" : "linear"
+                  }
+               }
             },
             "overrides" : []
          },
@@ -920,32 +894,135 @@
          },
          "id" : 18,
          "options" : {
+            "calculate" : false,
+            "cellGap" : 1,
+            "color" : {
+               "exponent" : 0.5,
+               "fill" : "dark-orange",
+               "mode" : "scheme",
+               "reverse" : false,
+               "scale" : "exponential",
+               "scheme" : "RdYlGn",
+               "steps" : 64
+            },
+            "exemplars" : {
+               "color" : "rgba(255,0,255,0.7)"
+            },
+            "filterValues" : {
+               "le" : 1e-09
+            },
             "legend" : {
-               "calcs" : [],
-               "displayMode" : "list",
-               "placement" : "bottom",
-               "showLegend" : true
+               "show" : true
+            },
+            "rowsFrame" : {
+               "layout" : "auto"
             },
             "tooltip" : {
                "mode" : "single",
-               "sort" : "none"
+               "showColorScale" : false,
+               "yHistogram" : false
+            },
+            "yAxis" : {
+               "axisPlacement" : "left",
+               "reverse" : false,
+               "unit" : "s"
             }
          },
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
+               "disableTextWrap" : false,
                "editorMode" : "builder",
                "exemplar" : false,
-               "expr" : "histogram_quantile(0.95, sum by(le) (rate(prosody_mod_csi_simple__buffer_hold_seconds_bucket{host=\"$virtualhost\"}[$__rate_interval])))",
-               "format" : "time_series",
+               "expr" : "rate(prosody_mod_csi_simple__buffer_hold_seconds_bucket{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[$__rate_interval])",
+               "format" : "heatmap",
+               "fullMetaSearch" : false,
+               "includeNullMetadata" : false,
                "instant" : false,
                "interval" : "",
-               "legendFormat" : "CSI hold seconds",
+               "legendFormat" : "__auto",
                "range" : true,
-               "refId" : "A"
+               "refId" : "A",
+               "useBackend" : false
             }
          ],
          "title" : "Hold time",
-         "type" : "timeseries"
+         "type" : "heatmap"
+      },
+      {
+         "fieldConfig" : {
+            "defaults" : {
+               "custom" : {
+                  "hideFrom" : {
+                     "legend" : false,
+                     "tooltip" : false,
+                     "viz" : false
+                  },
+                  "scaleDistribution" : {
+                     "type" : "linear"
+                  }
+               }
+            },
+            "overrides" : []
+         },
+         "gridPos" : {
+            "h" : 8,
+            "w" : 12,
+            "x" : 12,
+            "y" : 36
+         },
+         "id" : 20,
+         "options" : {
+            "calculate" : false,
+            "cellGap" : 1,
+            "color" : {
+               "exponent" : 0.5,
+               "fill" : "dark-orange",
+               "mode" : "scheme",
+               "reverse" : false,
+               "scale" : "exponential",
+               "scheme" : "PRGn",
+               "steps" : 64
+            },
+            "exemplars" : {
+               "color" : "rgba(255,0,255,0.7)"
+            },
+            "filterValues" : {
+               "le" : 1e-09
+            },
+            "legend" : {
+               "show" : true
+            },
+            "rowsFrame" : {
+               "layout" : "auto"
+            },
+            "tooltip" : {
+               "mode" : "single",
+               "showColorScale" : false,
+               "yHistogram" : false
+            },
+            "yAxis" : {
+               "axisPlacement" : "left",
+               "reverse" : false
+            }
+         },
+         "pluginVersion" : "11.6.0",
+         "targets" : [
+            {
+               "disableTextWrap" : false,
+               "editorMode" : "builder",
+               "expr" : "rate(prosody_mod_csi_simple__flush_stanza_count_bucket{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[$__rate_interval])",
+               "format" : "heatmap",
+               "fullMetaSearch" : false,
+               "includeNullMetadata" : false,
+               "legendFormat" : "Stanzas flushed",
+               "range" : true,
+               "refId" : "A",
+               "useBackend" : false
+            }
+         ],
+         "title" : "Flush sizes",
+         "type" : "heatmap"
       },
       {
          "fieldConfig" : {
@@ -960,7 +1037,103 @@
                   "axisLabel" : "",
                   "axisPlacement" : "auto",
                   "barAlignment" : 0,
-                  "drawStyle" : "points",
+                  "barWidthFactor" : 0.6,
+                  "drawStyle" : "line",
+                  "fillOpacity" : 50,
+                  "gradientMode" : "none",
+                  "hideFrom" : {
+                     "legend" : false,
+                     "tooltip" : false,
+                     "viz" : false
+                  },
+                  "insertNulls" : false,
+                  "lineInterpolation" : "smooth",
+                  "lineWidth" : 1,
+                  "pointSize" : 5,
+                  "scaleDistribution" : {
+                     "type" : "linear"
+                  },
+                  "showPoints" : "auto",
+                  "spanNulls" : false,
+                  "stacking" : {
+                     "group" : "A",
+                     "mode" : "percent"
+                  },
+                  "thresholdsStyle" : {
+                     "mode" : "off"
+                  }
+               },
+               "mappings" : [],
+               "thresholds" : {
+                  "mode" : "absolute",
+                  "steps" : [
+                     {
+                        "color" : "green"
+                     },
+                     {
+                        "color" : "red",
+                        "value" : 80
+                     }
+                  ]
+               },
+               "unit" : "none"
+            },
+            "overrides" : []
+         },
+         "gridPos" : {
+            "h" : 8,
+            "w" : 12,
+            "x" : 0,
+            "y" : 44
+         },
+         "id" : 32,
+         "options" : {
+            "legend" : {
+               "calcs" : [],
+               "displayMode" : "list",
+               "placement" : "bottom",
+               "showLegend" : true
+            },
+            "tooltip" : {
+               "hideZeros" : false,
+               "mode" : "single",
+               "sort" : "none"
+            }
+         },
+         "pluginVersion" : "11.6.0",
+         "targets" : [
+            {
+               "disableTextWrap" : false,
+               "editorMode" : "builder",
+               "expr" : "avg_over_time(prosody_mod_csi__state_sessions{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[$__interval])",
+               "format" : "time_series",
+               "fullMetaSearch" : false,
+               "includeNullMetadata" : true,
+               "legendFormat" : "{{csi_state}}",
+               "range" : true,
+               "refId" : "A",
+               "useBackend" : false
+            }
+         ],
+         "title" : "CSI States",
+         "type" : "timeseries"
+      },
+      {
+         "description" : "This panel requires [mod_measure_conn_buffers](https://modules.prosody.im/mod_measure_conn_buffers.html)",
+         "fieldConfig" : {
+            "defaults" : {
+               "color" : {
+                  "mode" : "palette-classic"
+               },
+               "custom" : {
+                  "axisBorderShow" : false,
+                  "axisCenteredZero" : false,
+                  "axisColorMode" : "text",
+                  "axisLabel" : "",
+                  "axisPlacement" : "auto",
+                  "barAlignment" : 0,
+                  "barWidthFactor" : 0.6,
+                  "drawStyle" : "line",
                   "fillOpacity" : 0,
                   "gradientMode" : "none",
                   "hideFrom" : {
@@ -998,7 +1171,7 @@
                      }
                   ]
                },
-               "unit" : "none"
+               "unit" : "bytes"
             },
             "overrides" : []
          },
@@ -1006,9 +1179,9 @@
             "h" : 8,
             "w" : 12,
             "x" : 12,
-            "y" : 36
+            "y" : 44
          },
-         "id" : 20,
+         "id" : 33,
          "options" : {
             "legend" : {
                "calcs" : [],
@@ -1017,21 +1190,26 @@
                "showLegend" : true
             },
             "tooltip" : {
+               "hideZeros" : false,
                "mode" : "single",
                "sort" : "none"
             }
          },
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
+               "disableTextWrap" : false,
                "editorMode" : "builder",
-               "expr" : "histogram_quantile(0.95, sum by(le) (rate(prosody_mod_csi_simple__flush_stanza_count_bucket{host=\"$virtualhost\"}[$__rate_interval])))",
-               "format" : "time_series",
-               "legendFormat" : "Stanzas flushed",
+               "expr" : "max_over_time(prosody_mod_measure_conn_buffers__total_pending_tx{job=~\"$job\",instance=~\"$instance\",host=\"\"}[$__interval])",
+               "fullMetaSearch" : false,
+               "includeNullMetadata" : true,
+               "legendFormat" : "{{instance}}",
                "range" : true,
-               "refId" : "A"
+               "refId" : "A",
+               "useBackend" : false
             }
          ],
-         "title" : "Flush sizes",
+         "title" : "Connection Buffers",
          "type" : "timeseries"
       },
       {
@@ -1040,7 +1218,7 @@
             "h" : 1,
             "w" : 24,
             "x" : 0,
-            "y" : 44
+            "y" : 52
          },
          "id" : 22,
          "panels" : [],
@@ -1048,17 +1226,6 @@
          "type" : "row"
       },
       {
-         "cards" : {},
-         "color" : {
-            "cardColor" : "#b4ff00",
-            "colorScale" : "sqrt",
-            "colorScheme" : "interpolateRdYlGn",
-            "exponent" : 0.5,
-            "max" : 5,
-            "min" : 0,
-            "mode" : "opacity"
-         },
-         "dataFormat" : "tsbuckets",
          "fieldConfig" : {
             "defaults" : {
                "custom" : {
@@ -1078,20 +1245,16 @@
             "h" : 8,
             "w" : 18,
             "x" : 0,
-            "y" : 45
+            "y" : 53
          },
-         "heatmap" : {},
-         "hideZeroBuckets" : false,
-         "highlightCards" : true,
          "id" : 8,
-         "legend" : {
-            "show" : false
-         },
          "options" : {
             "calculate" : false,
             "calculation" : {},
             "cellGap" : 2,
-            "cellValues" : {},
+            "cellValues" : {
+               "decimals" : 0
+            },
             "color" : {
                "exponent" : 0.5,
                "fill" : "#b4ff00",
@@ -1117,7 +1280,8 @@
             },
             "showValue" : "never",
             "tooltip" : {
-               "show" : true,
+               "mode" : "single",
+               "showColorScale" : false,
                "yHistogram" : false
             },
             "yAxis" : {
@@ -1126,18 +1290,17 @@
                "unit" : "bytes"
             }
          },
-         "pluginVersion" : "10.2.0",
-         "reverseYBuckets" : false,
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
                "disableTextWrap" : false,
                "editorMode" : "builder",
                "exemplar" : true,
-               "expr" : "sum by(le) (changes(prosody_mod_http_file_share__upload_bytes_bucket{host=\"$virtualhost\"}[$__interval]))",
+               "expr" : "sum by(le) (increase(prosody_mod_http_file_share__upload_bytes_bucket{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[1h]))",
                "format" : "heatmap",
                "fullMetaSearch" : false,
                "includeNullMetadata" : true,
-               "interval" : "3600s",
+               "interval" : "1h",
                "intervalFactor" : 1,
                "legendFormat" : "{{le}}",
                "range" : true,
@@ -1146,20 +1309,7 @@
             }
          ],
          "title" : "Upload sizes",
-         "tooltip" : {
-            "show" : true,
-            "showHistogram" : false
-         },
-         "type" : "heatmap",
-         "xAxis" : {
-            "show" : true
-         },
-         "yAxis" : {
-            "format" : "bytes",
-            "logBase" : 1,
-            "show" : true
-         },
-         "yBucketBound" : "upper"
+         "type" : "heatmap"
       },
       {
          "fieldConfig" : {
@@ -1186,7 +1336,7 @@
             "h" : 8,
             "w" : 6,
             "x" : 18,
-            "y" : 45
+            "y" : 53
          },
          "id" : 10,
          "options" : {
@@ -1202,14 +1352,15 @@
             },
             "showThresholdLabels" : false,
             "showThresholdMarkers" : false,
+            "sizing" : "auto",
             "text" : {}
          },
-         "pluginVersion" : "10.2.0",
+         "pluginVersion" : "11.6.0",
          "targets" : [
             {
                "editorMode" : "builder",
                "exemplar" : true,
-               "expr" : "prosody_mod_http_file_share__total_storage_bytes{host=\"$virtualhost\"}",
+               "expr" : "prosody_mod_http_file_share__total_storage_bytes{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}",
                "instant" : false,
                "interval" : "",
                "legendFormat" : "",
@@ -1218,10 +1369,226 @@
          ],
          "title" : "Total uploads",
          "type" : "gauge"
+      },
+      {
+         "collapsed" : false,
+         "gridPos" : {
+            "h" : 1,
+            "w" : 24,
+            "x" : 0,
+            "y" : 61
+         },
+         "id" : 34,
+         "panels" : [],
+         "title" : "Spam",
+         "type" : "row"
+      },
+      {
+         "description" : "This panel requires [mod_anti_spam](https://modules.prosody.im/mod_anti_spam.html)",
+         "fieldConfig" : {
+            "defaults" : {
+               "color" : {
+                  "mode" : "palette-classic"
+               },
+               "custom" : {
+                  "axisBorderShow" : false,
+                  "axisCenteredZero" : false,
+                  "axisColorMode" : "text",
+                  "axisLabel" : "",
+                  "axisPlacement" : "auto",
+                  "barAlignment" : 0,
+                  "barWidthFactor" : 0.6,
+                  "drawStyle" : "line",
+                  "fillOpacity" : 0,
+                  "gradientMode" : "none",
+                  "hideFrom" : {
+                     "legend" : false,
+                     "tooltip" : false,
+                     "viz" : false
+                  },
+                  "insertNulls" : false,
+                  "lineInterpolation" : "linear",
+                  "lineWidth" : 1,
+                  "pointSize" : 5,
+                  "scaleDistribution" : {
+                     "type" : "linear"
+                  },
+                  "showPoints" : "auto",
+                  "spanNulls" : false,
+                  "stacking" : {
+                     "group" : "A",
+                     "mode" : "none"
+                  },
+                  "thresholdsStyle" : {
+                     "mode" : "off"
+                  }
+               },
+               "mappings" : [],
+               "thresholds" : {
+                  "mode" : "absolute",
+                  "steps" : [
+                     {
+                        "color" : "green"
+                     },
+                     {
+                        "color" : "red",
+                        "value" : 80
+                     }
+                  ]
+               },
+               "unit" : "pps"
+            },
+            "overrides" : []
+         },
+         "gridPos" : {
+            "h" : 8,
+            "w" : 12,
+            "x" : 0,
+            "y" : 62
+         },
+         "id" : 36,
+         "options" : {
+            "legend" : {
+               "calcs" : [],
+               "displayMode" : "list",
+               "placement" : "bottom",
+               "showLegend" : true
+            },
+            "tooltip" : {
+               "hideZeros" : false,
+               "mode" : "single",
+               "sort" : "none"
+            }
+         },
+         "pluginVersion" : "11.6.0",
+         "targets" : [
+            {
+               "disableTextWrap" : false,
+               "editorMode" : "builder",
+               "expr" : "rate(prosody_mod_anti_spam__anti_spam_blocked_stanzas_total{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[$__rate_interval])",
+               "fullMetaSearch" : false,
+               "includeNullMetadata" : true,
+               "legendFormat" : "{{reason}}",
+               "range" : true,
+               "refId" : "A",
+               "useBackend" : false
+            }
+         ],
+         "title" : "mod_anti_spam",
+         "type" : "timeseries"
+      },
+      {
+         "description" : "This panel requires [mod_spam_reporting](https://modules.prosody.im/mod_spam_reporting.html) and [mod_report_forward](https://modules.prosody.im/mod_report_forward.html)",
+         "fieldConfig" : {
+            "defaults" : {
+               "color" : {
+                  "mode" : "palette-classic"
+               },
+               "custom" : {
+                  "axisBorderShow" : false,
+                  "axisCenteredZero" : false,
+                  "axisColorMode" : "text",
+                  "axisLabel" : "",
+                  "axisPlacement" : "auto",
+                  "barAlignment" : 0,
+                  "barWidthFactor" : 1,
+                  "drawStyle" : "line",
+                  "fillOpacity" : 25,
+                  "gradientMode" : "none",
+                  "hideFrom" : {
+                     "legend" : false,
+                     "tooltip" : false,
+                     "viz" : false
+                  },
+                  "insertNulls" : false,
+                  "lineInterpolation" : "smooth",
+                  "lineWidth" : 1,
+                  "pointSize" : 5,
+                  "scaleDistribution" : {
+                     "type" : "linear"
+                  },
+                  "showPoints" : "auto",
+                  "spanNulls" : false,
+                  "stacking" : {
+                     "group" : "A",
+                     "mode" : "none"
+                  },
+                  "thresholdsStyle" : {
+                     "mode" : "off"
+                  }
+               },
+               "mappings" : [],
+               "thresholds" : {
+                  "mode" : "absolute",
+                  "steps" : [
+                     {
+                        "color" : "green"
+                     },
+                     {
+                        "color" : "red",
+                        "value" : 80
+                     }
+                  ]
+               },
+               "unit" : "pps"
+            },
+            "overrides" : []
+         },
+         "gridPos" : {
+            "h" : 8,
+            "w" : 12,
+            "x" : 12,
+            "y" : 62
+         },
+         "id" : 35,
+         "options" : {
+            "legend" : {
+               "calcs" : [],
+               "displayMode" : "list",
+               "placement" : "bottom",
+               "showLegend" : true
+            },
+            "tooltip" : {
+               "hideZeros" : false,
+               "mode" : "single",
+               "sort" : "none"
+            }
+         },
+         "pluginVersion" : "11.6.0",
+         "targets" : [
+            {
+               "disableTextWrap" : false,
+               "editorMode" : "builder",
+               "expr" : "rate(prosody_mod_spam_reporting__received_reports_total{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[$__rate_interval])",
+               "fullMetaSearch" : false,
+               "includeNullMetadata" : true,
+               "interval" : "",
+               "legendFormat" : "{{report_type}} reports",
+               "range" : true,
+               "refId" : "A",
+               "useBackend" : false
+            },
+            {
+               "disableTextWrap" : false,
+               "editorMode" : "code",
+               "expr" : "-rate(prosody_mod_report_forward__forwarded_reports_total{job=~\"$job\",instance=~\"$instance\",host=~\"$virtualhost\"}[$__rate_interval])",
+               "fullMetaSearch" : false,
+               "hide" : false,
+               "includeNullMetadata" : true,
+               "instant" : false,
+               "legendFormat" : "forwarded",
+               "range" : true,
+               "refId" : "B",
+               "useBackend" : false
+            }
+         ],
+         "title" : "Reports",
+         "type" : "timeseries"
       }
    ],
+   "preload" : false,
    "refresh" : "5m",
-   "schemaVersion" : 38,
+   "schemaVersion" : 41,
    "tags" : [
       "prosody",
       "xmpp"
@@ -1229,21 +1596,57 @@
    "templating" : {
       "list" : [
          {
-            "definition" : "label_values(host)",
-            "hide" : 0,
-            "includeAll" : false,
-            "label" : "VirtualHost",
-            "multi" : false,
-            "name" : "virtualhost",
+            "current" : {
+               "text" : "prosody",
+               "value" : "prosody"
+            },
+            "definition" : "label_values(prosody_info,job)",
+            "label" : "Job",
+            "name" : "job",
             "options" : [],
             "query" : {
-               "query" : "label_values(host)",
+               "qryType" : 1,
+               "query" : "label_values(prosody_info,job)",
                "refId" : "PrometheusVariableQueryEditor-VariableQuery"
             },
             "refresh" : 1,
             "regex" : "",
-            "skipUrlSync" : false,
-            "sort" : 0,
+            "type" : "query"
+         },
+         {
+            "current" : {
+               "text" : "All",
+               "value" : [
+                  "$__all"
+               ]
+            },
+            "definition" : "label_values(prosody_info{job=~\"$job\"},instance)",
+            "includeAll" : true,
+            "multi" : true,
+            "name" : "instance",
+            "options" : [],
+            "query" : {
+               "qryType" : 1,
+               "query" : "label_values(prosody_info{job=~\"$job\"},instance)",
+               "refId" : "PrometheusVariableQueryEditor-VariableQuery"
+            },
+            "refresh" : 1,
+            "regex" : "",
+            "type" : "query"
+         },
+         {
+            "definition" : "label_values({job=~\"$job\", instance=~\"$instance\"},host)",
+            "includeAll" : false,
+            "label" : "VirtualHost",
+            "name" : "virtualhost",
+            "options" : [],
+            "query" : {
+               "qryType" : 1,
+               "query" : "label_values({job=~\"$job\", instance=~\"$instance\"},host)",
+               "refId" : "PrometheusVariableQueryEditor-VariableQuery"
+            },
+            "refresh" : 1,
+            "regex" : "",
             "type" : "query"
          }
       ]
@@ -1256,6 +1659,5 @@
    "timezone" : "",
    "title" : "Prosody",
    "uid" : "y1Onovt7z",
-   "version" : 91,
-   "weekStart" : ""
+   "version" : 134
 }
--- a/mod_conversejs/mod_conversejs.lua	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_conversejs/mod_conversejs.lua	Tue Apr 29 23:27:06 2025 +0700
@@ -110,10 +110,10 @@
 
 local add_tags = module:get_option_array("conversejs_tags", {});
 
-local service_name = module:get_option_string("name", "Prosody IM and Converse.js");
-local service_short_name = module:get_option_string("short_name", "Converse");
-local service_description = module:get_option_string("description", "Messaging Freedom")
-local pwa_color = module:get_option_string("pwa_color", "#397491")
+local service_name = module:get_option_string("conversejs_name", module:get_option_string("name", "Prosody IM and Converse.js"));
+local service_short_name = module:get_option_string("conversejs_short_name", "Converse");
+local service_description = module:get_option_string("conversejs_description", "Messaging Freedom")
+local pwa_color = module:get_option_string("conversejs_pwa_color", "#397491")
 
 module:provides("http", {
 	title = "Converse.js";
--- a/mod_http_oauth2/README.md	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_http_oauth2/README.md	Tue Apr 29 23:27:06 2025 +0700
@@ -86,6 +86,15 @@
 oauth2_security_policy = "default-src 'self'" -- this is the default
 ```
 
+For the Resource Owner Password Grant the `username` is expected to be the only
+localpart by default.  If the OAuth client includes the domainpart in the
+`username` it submits (e.g. user@example.org instead of just user), set this to
+`true`. Note that this requires all clients to follow this format.
+
+```lua
+oauth2_expect_username_jid = false
+```
+
 ### Token parameters
 
 The following options configure the lifetime of tokens issued by the module.
--- a/mod_http_oauth2/mod_http_oauth2.lua	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_http_oauth2/mod_http_oauth2.lua	Tue Apr 29 23:27:06 2025 +0700
@@ -134,6 +134,7 @@
 
 local pkce_required = module:get_option_boolean("oauth2_require_code_challenge", true);
 local respect_prompt = module:get_option_boolean("oauth2_respect_oidc_prompt", false);
+local expect_username_jid = module:get_option_boolean("oauth2_expect_username_jid", false);
 
 local verification_key;
 local sign_client, verify_client;
@@ -397,21 +398,52 @@
 	return oauth_error("invalid_request");
 end
 
+local function make_client_secret(client_id) --> client_secret
+       return hashes.hmac_sha256(verification_key, client_id, true);
+end
+
+local function verify_client_secret(client_id, client_secret)
+       return hashes.equals(make_client_secret(client_id), client_secret);
+end
+
 function grant_type_handlers.password(params)
-	local request_jid = assert(params.username, oauth_error("invalid_request", "missing 'username' (JID)"));
-	local request_password = assert(params.password, oauth_error("invalid_request", "missing 'password'"));
-	local request_username, request_host, request_resource = jid.prepped_split(request_jid);
+	if not params.client_id then return oauth_error("invalid_request", "missing 'client_id'"); end
+	if not params.client_secret then return oauth_error("invalid_request", "missing 'client_secret'"); end
+
+	local client = check_client(params.client_id);
+	if not client then
+		return oauth_error("invalid_client", "incorrect credentials");
+	end
 
-	if not (request_username and request_host) or request_host ~= module.host then
-		return oauth_error("invalid_request", "invalid JID");
+	if not verify_client_secret(params.client_id, params.client_secret) then
+		module:log("debug", "client_secret mismatch");
+		return oauth_error("invalid_client", "incorrect credentials");
 	end
-	if not usermanager.test_password(request_username, request_host, request_password) then
+
+	local request_username
+
+	if expect_username_jid then
+		local request_jid = assert(params.username, oauth_error("invalid_request", "missing 'username' (JID)"));
+		local _request_username, request_host, request_resource = jid.prepped_split(request_jid);
+
+		if not (_request_username and request_host) or request_host ~= module.host then
+			return oauth_error("invalid_request", "invalid JID");
+		end
+
+		request_username = _request_username
+	else
+		request_username = assert(params.username, oauth_error("invalid_request", "missing 'username'"));
+	end
+
+	local request_password = assert(params.password, oauth_error("invalid_request", "missing 'password'"));
+
+	if not usermanager.test_password(request_username, module.host, request_password) then
 		return oauth_error("invalid_grant", "incorrect credentials");
 	end
 
-	local granted_jid = jid.join(request_username, request_host, request_resource);
+	local granted_jid = jid.join(request_username, module.host);
 	local granted_scopes, granted_role = filter_scopes(request_username, params.scope);
-	return json.encode(new_access_token(granted_jid, granted_role, granted_scopes, nil));
+	return json.encode(new_access_token(granted_jid, granted_role, granted_scopes, client));
 end
 
 function response_type_handlers.code(client, params, granted_jid, id_token)
@@ -505,14 +537,6 @@
 	}
 end
 
-local function make_client_secret(client_id) --> client_secret
-	return hashes.hmac_sha256(verification_key, client_id, true);
-end
-
-local function verify_client_secret(client_id, client_secret)
-	return hashes.equals(make_client_secret(client_id), client_secret);
-end
-
 function grant_type_handlers.authorization_code(params)
 	if not params.client_id then return oauth_error("invalid_request", "missing 'client_id'"); end
 	if not params.client_secret then return oauth_error("invalid_request", "missing 'client_secret'"); end
--- a/mod_invites_page/mod_invites_page.lua	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_invites_page/mod_invites_page.lua	Tue Apr 29 23:27:06 2025 +0700
@@ -61,6 +61,8 @@
 	-- so the user will only receive a URI. The client should be able to handle this
 	-- by automatically falling back to a client-specific landing page, per XEP-0401.
 	if not invite.allow_registration then return; end
+	-- password reset invites are not currently supported
+	if invite.additional_data and invite.additional_data.allow_reset then return end
 	invite.landing_page = render_url(invite_url_template, { host = module.host, invite = invite });
 end
 
--- a/mod_post_msg/README.md	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_post_msg/README.md	Tue Apr 29 23:27:06 2025 +0700
@@ -32,9 +32,9 @@
 Authentication
 --------------
 
-Authentication is done by HTTP Basic.
+Authentication is done by [HTTP Basic](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication).
 
-    Authentication: Basic BASE64( "username@virtualhost:password" )
+    Authorization: Basic BASE64( "username@virtualhost:password" )
 
 Payload formats
 ---------------
--- a/mod_push2/mod_push2.lua	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_push2/mod_push2.lua	Tue Apr 29 23:27:06 2025 +0700
@@ -33,7 +33,7 @@
 local function parse_match(matchel)
 		local match = { match = matchel.attr.profile, chats = {} }
 
-		for chatel in matchel:childtags("chat") do
+		for chatel in matchel:childtags("filter") do
 			local chat = {}
 			if chatel:get_child("mention") then
 				chat.mention = true
--- a/mod_push2/push2.md	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_push2/push2.md	Tue Apr 29 23:27:06 2025 +0700
@@ -16,9 +16,9 @@
     <client>https://push.example.com/adlfkjadafdasf</client>
     <match profile="urn:xmpp:push2:match:archived-with-body">
         <grace>144</grace>
-        <chat jid="somemuc@conference.example.com">
+        <filter jid="somemuc@conference.example.com">
             <mention/>
-        </chat>
+        </filter>
         <send xmlns="urn:xmpp:push2:send:notify-only:0"/>
     </match>
 </enable>
@@ -30,7 +30,7 @@
 
 The `<match/>` and `<send/>` elements define what profiles to use for matching stanzas and sending notifications. These are described later in this document.
 
-The optional `<chat/>` child of `<match/>` allows extra filtering of pushes for only specific chats. No specified filters means muted, do not push. `<mention/>` means push on mentions, `<reply/>` means push on replies.
+The optional `<filter/>` child of `<match/>` allows extra filtering of pushes for only specific chats. No specified filters means muted, do not push. `<mention/>` means push on mentions, `<reply/>` means push on replies.
 
 The optional `<grace/>` child of `<match/>` allows specifying a "grace period" in seconds where activity on another session by the same user (such as sending a message) will temporarily pause sending push notifications.
 
--- a/mod_rest/README.md	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_rest/README.md	Tue Apr 29 23:27:06 2025 +0700
@@ -63,11 +63,10 @@
 and lastly, drop the "@host" from the username in your http queries, EG:
 
 ```lua
-curl \
-  https://chat.example.com:5281/rest/version/chat.example.com \
-  -k \
+curl -sf \
+  -H 'Accept: application/json' \
   --user admin \
-  -H 'Accept: application/json'
+  https://chat.example.com:5281/rest/version/chat.example.com
 ```
 
 ## OAuth2
--- a/mod_rest/mod_rest.lua	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_rest/mod_rest.lua	Tue Apr 29 23:27:06 2025 +0700
@@ -664,6 +664,7 @@
 
 -- strip some stuff, notably the optional traceback table that casues stack overflow in util.json
 local function simplify_error(e)
+	if not e then return end
 	return {
 		type = e.type;
 		condition = e.condition;