openship 0.5.0 → 0.6.0

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.
Files changed (103) hide show
  1. package/README.md +26 -1
  2. package/dist/bare-FSUAM5V5.js +23 -0
  3. package/dist/{bowser-O3AEA6AN.js → bowser-HNOTPGJO.js} +2 -2
  4. package/dist/{chunk-5MZ624VX.js → chunk-2GWYYHOR.js} +1 -1
  5. package/dist/chunk-3FYIXVX5.js +8051 -0
  6. package/dist/{chunk-ILFETZOM.js → chunk-3LDWWY7U.js} +21 -1
  7. package/dist/{chunk-W73X43R7.js → chunk-3NQQXMDR.js} +3 -3
  8. package/dist/{chunk-OWED2GRM.js → chunk-42WQABXM.js} +2 -2
  9. package/dist/{chunk-TYVME3XD.js → chunk-6FH4AXVY.js} +20 -3
  10. package/dist/{chunk-ZCOQJCZO.js → chunk-6ODUBKUB.js} +3 -3
  11. package/dist/{chunk-DYPH4HCI.js → chunk-AO252K7Z.js} +1 -1
  12. package/dist/{chunk-K2RPVGPN.js → chunk-B3CE2OMR.js} +14 -12
  13. package/dist/{chunk-IXCHURVK.js → chunk-DOD2BXHQ.js} +4 -4
  14. package/dist/{chunk-VWPEKOH6.js → chunk-DRK3MEDS.js} +3 -3
  15. package/dist/{chunk-V7BZMGOT.js → chunk-EMXI4UCU.js} +5 -5
  16. package/dist/{chunk-NNPEG6HM.js → chunk-EP2TNALB.js} +2 -2
  17. package/dist/{chunk-NXFIRK2Z.js → chunk-GUQ3QCJ7.js} +573 -459
  18. package/dist/chunk-I3DPMTSF.js +29 -0
  19. package/dist/{chunk-KZOBYJUW.js → chunk-IW2UKBVF.js} +3 -3
  20. package/dist/{chunk-YWMODKWL.js → chunk-IXM5245F.js} +165 -13
  21. package/dist/{chunk-KNTJ7PSF.js → chunk-JIMUYEKN.js} +4 -4
  22. package/dist/chunk-OGY63DGD.js +705 -0
  23. package/dist/{chunk-O6ZZF52V.js → chunk-ONKEYSMY.js} +2 -2
  24. package/dist/{chunk-UMQP7SYT.js → chunk-OTLSJYAC.js} +1316 -53
  25. package/dist/{chunk-EI575GHN.js → chunk-PDW4L3NV.js} +3 -3
  26. package/dist/{chunk-JLKKYUZA.js → chunk-PSZSKEPA.js} +7 -7
  27. package/dist/{chunk-KI2EY3WB.js → chunk-PXKCZB2I.js} +1 -1
  28. package/dist/{chunk-RB35YN3J.js → chunk-QEH4QUBX.js} +391 -63
  29. package/dist/{chunk-6APIPIJY.js → chunk-QWHBRY2K.js} +5 -5
  30. package/dist/{chunk-6B5YCFFV.js → chunk-RVER2EOO.js} +5 -5
  31. package/dist/{chunk-Q2CIRAOK.js → chunk-RXQBD4ZY.js} +1 -1
  32. package/dist/{chunk-6LKHXB6T.js → chunk-TWJCLD4W.js} +48 -13
  33. package/dist/{chunk-I6PSTQIR.js → chunk-VDDMADOF.js} +3 -3
  34. package/dist/{chunk-BS2AXYZX.js → chunk-VE2YOK4I.js} +626 -214
  35. package/dist/{chunk-6PIYRG5I.js → chunk-VZ2ZHPS2.js} +52 -42
  36. package/dist/{chunk-AVIB7CT7.js → chunk-WNWQBB7F.js} +2 -2
  37. package/dist/{chunk-FRNAR33O.js → chunk-XZYFZ6A5.js} +3 -3
  38. package/dist/{chunk-RPHRPFEH.js → chunk-ZCFVHA25.js} +1 -1
  39. package/dist/{chunk-FPRHYBY2.js → chunk-ZFJXPCQP.js} +1 -1
  40. package/dist/{chunk-JYGD5WSN.js → chunk-ZWLDLTJP.js} +1 -1
  41. package/dist/cloud-E5M6VMCG.js +31 -0
  42. package/dist/{cloud-7QYOGF7F.js → cloud-KRTZ2IL5.js} +3 -3
  43. package/dist/{detect-BAJMY6KM.js → detect-ALF4GXRX.js} +7 -8
  44. package/dist/{dist-IQJ6H6UZ.js → dist-BM6NPWIH.js} +3 -3
  45. package/dist/{dist-es-X3B5QYKB.js → dist-es-2YRDXMUU.js} +6 -6
  46. package/dist/{dist-es-OSNJBLXB.js → dist-es-CCVZEFRZ.js} +5 -5
  47. package/dist/{dist-es-VNKHQVIB.js → dist-es-IOH6G4GM.js} +4 -4
  48. package/dist/{dist-es-RYHIPOTN.js → dist-es-JGBPABJI.js} +14 -14
  49. package/dist/{dist-es-JSTDUS7Q.js → dist-es-KWSMDPIP.js} +6 -6
  50. package/dist/{dist-es-5DY7K32L.js → dist-es-UYDDOVZ3.js} +6 -6
  51. package/dist/{dist-es-WV4AMOII.js → dist-es-XUOR4NQN.js} +8 -8
  52. package/dist/docker-QECQJ5P4.js +32 -0
  53. package/dist/docker-edge-executor-62N64MGS.js +17 -0
  54. package/dist/edge-import-CQWHN2Q3.js +48 -0
  55. package/dist/ensure-container-edge-MJVXJQG5.js +32 -0
  56. package/dist/{event-streams-EHRAKL75.js → event-streams-TR4GAC53.js} +4 -4
  57. package/dist/{executor-LOYMPU67.js → executor-JELARVKC.js} +8 -8
  58. package/dist/index.js +1170 -459
  59. package/dist/{loadSso-46FQRIZS.js → loadSso-UGF4JMRK.js} +10 -10
  60. package/dist/{local-executor-V7U5VOZW.js → local-executor-WOFZD72X.js} +4 -4
  61. package/dist/nginx-AXGNWRKZ.js +31 -0
  62. package/dist/node-entry.js +4 -0
  63. package/dist/{noop-FMMFG2EZ.js → noop-NJ72F46T.js} +3 -3
  64. package/dist/openresty-lua-IE4P5YQX.js +81 -0
  65. package/dist/server/index.js +23172 -7994
  66. package/dist/server/lua/geo_country.lua +31 -6
  67. package/dist/server/lua/maxminddb.lua +403 -0
  68. package/dist/server/lua/mgmt_api.lua +431 -68
  69. package/dist/server/lua/pipe_log.lua +10 -4
  70. package/dist/server/lua/site_logger.lua +220 -12
  71. package/dist/server/migrations/0082_edge_target_verification.sql +39 -0
  72. package/dist/server/migrations/0083_service_incident.sql +84 -0
  73. package/dist/server/migrations/0084_analytics_daily_rollup.sql +72 -0
  74. package/dist/server/migrations/0085_resource_usage.sql +68 -0
  75. package/dist/server/migrations/0086_remote_infra_updates.sql +41 -0
  76. package/dist/server/migrations/0087_server_container_version_columns.sql +17 -0
  77. package/dist/server/migrations/0088_audit_source_and_settings.sql +27 -0
  78. package/dist/server/migrations/0089_auto_scan_infra.sql +7 -0
  79. package/dist/server/migrations/0090_project_collect_paths.sql +18 -0
  80. package/dist/server/migrations/0091_project_server_id.sql +26 -0
  81. package/dist/server/migrations/0092_project_internal_alias.sql +13 -0
  82. package/dist/server/migrations/0093_service_incident_org_index.sql +13 -0
  83. package/dist/server/migrations/0094_backup_restore_meta.sql +15 -0
  84. package/dist/server/migrations/0095_backup_restore_cancel.sql +19 -0
  85. package/dist/server/migrations/0096_backup_policy_retention_defaults.sql +20 -0
  86. package/dist/server/migrations/0097_update_status_upstream_only.sql +35 -0
  87. package/dist/server/migrations/meta/_journal.json +112 -0
  88. package/dist/setup-FA4PW4NU.js +21 -0
  89. package/dist/{signin-ITOPKKUB.js → signin-3M3UPB6K.js} +10 -10
  90. package/dist/{sso-oidc-NON2PD7Y.js → sso-oidc-3VDIYOEJ.js} +10 -10
  91. package/dist/{sts-HHFFSAY2.js → sts-B3WIYLXR.js} +9 -9
  92. package/package.json +6 -3
  93. package/dist/bare-VRGE5MXH.js +0 -23
  94. package/dist/chunk-CUJXGK7R.js +0 -3167
  95. package/dist/chunk-EAAGSQXN.js +0 -377
  96. package/dist/cloud-3M2WZ624.js +0 -30
  97. package/dist/docker-2NGBRJFJ.js +0 -18
  98. package/dist/docker-edge-executor-5I4M5QT7.js +0 -13
  99. package/dist/edge-import-RIWNEIXQ.js +0 -47
  100. package/dist/ensure-container-edge-3NSYKHRX.js +0 -31
  101. package/dist/nginx-QE4DOM5J.js +0 -24
  102. package/dist/openresty-lua-BTAKECCF.js +0 -42
  103. package/dist/setup-KELALK7H.js +0 -20
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  __export
7
- } from "./chunk-KI2EY3WB.js";
7
+ } from "./chunk-PXKCZB2I.js";
8
8
 
9
9
  // ../../packages/core/src/stacks.ts
10
10
  var LANGUAGES = {
@@ -153,6 +153,34 @@ var STACKS = {
153
153
  deps: ["@remix-run/react", "@remix-run/node", "remix"]
154
154
  }
155
155
  },
156
+ "tanstack-start": {
157
+ name: "TanStack Start",
158
+ language: "typescript",
159
+ category: "fullstack",
160
+ outputDirectory: ".output",
161
+ defaultPort: 3e3,
162
+ defaultBuildCommand: "vite build",
163
+ defaultStartCommand: "node .output/server/index.mjs",
164
+ // Nitro/Vinxi server bundle is self-contained under .output — same shape as Nuxt.
165
+ productionPaths: [".output"],
166
+ detection: {
167
+ // TanStack Start is Vite/Rsbuild-based; app.config.* is the older
168
+ // framework-specific marker, while current apps commonly ship vite.config.*
169
+ // or rsbuild.config.* plus the start package dep.
170
+ rootMarkers: [
171
+ "app.config.ts",
172
+ "app.config.js",
173
+ "app.config.mjs",
174
+ "vite.config.ts",
175
+ "vite.config.js",
176
+ "vite.config.mjs",
177
+ "rsbuild.config.ts",
178
+ "rsbuild.config.js",
179
+ "rsbuild.config.mjs"
180
+ ],
181
+ deps: ["@tanstack/react-start", "@tanstack/start"]
182
+ }
183
+ },
156
184
  astro: {
157
185
  name: "Astro",
158
186
  language: "typescript",
@@ -810,6 +838,7 @@ var STACK_ICONS = {
810
838
  nuxt: `${DI}/nuxtjs/nuxtjs-original.svg`,
811
839
  sveltekit: `${DI}/svelte/svelte-original.svg`,
812
840
  remix: `${DI}/react/react-original.svg`,
841
+ "tanstack-start": `${DI}/react/react-original.svg`,
813
842
  astro: `${DI}/astro/astro-original.svg`,
814
843
  vite: `${DI}/vitejs/vitejs-original.svg`,
815
844
  angular: `${DI}/angular/angular-original.svg`,
@@ -1012,17 +1041,26 @@ var CREDIT_PACKS = [
1012
1041
  }
1013
1042
  ];
1014
1043
 
1015
- // ../../packages/core/src/edge-image-ref.ts
1016
- function buildEdgeImageRef(opts) {
1044
+ // ../../packages/core/src/image-ref.ts
1045
+ function buildImageRef(opts, image) {
1017
1046
  const explicit = opts?.explicit?.trim();
1018
1047
  if (explicit) return explicit;
1019
- const override = process.env.OPENSHIP_EDGE_IMAGE?.trim();
1048
+ const override = image.imageOverride?.trim();
1020
1049
  if (override) return override;
1021
1050
  const injected = opts?.injectedDefault?.trim();
1022
1051
  if (injected) return injected;
1023
1052
  const registry2 = process.env.OPENSHIP_IMAGE_REGISTRY?.trim() || DEFAULT_IMAGE_REGISTRY;
1024
- const tag = process.env.OPENSHIP_EDGE_TAG?.trim() || process.env.OPENSHIP_VERSION?.trim() || opts?.fallbackTag?.trim() || "latest";
1025
- return `${registry2}/openship-edge:${tag}`;
1053
+ const tag = image.tagOverride?.trim() || process.env.OPENSHIP_VERSION?.trim() || opts?.fallbackTag?.trim() || "latest";
1054
+ return `${registry2}/${image.name}:${tag}`;
1055
+ }
1056
+
1057
+ // ../../packages/core/src/edge-image-ref.ts
1058
+ function buildEdgeImageRef(opts) {
1059
+ return buildImageRef(opts, {
1060
+ name: "openship-edge",
1061
+ imageOverride: process.env.OPENSHIP_EDGE_IMAGE,
1062
+ tagOverride: process.env.OPENSHIP_EDGE_TAG
1063
+ });
1026
1064
  }
1027
1065
 
1028
1066
  // ../../packages/core/src/system.ts
@@ -1096,6 +1134,12 @@ var SYSTEM = {
1096
1134
  // 4 hours
1097
1135
  /** Keep-alive heartbeat interval (ms) - prevents proxy/CDN drops */
1098
1136
  HEARTBEAT_INTERVAL_MS: 25e3,
1137
+ /**
1138
+ * How long a finished handler waits for already-queued frames to flush
1139
+ * before the stream closes. Bounded because a client that has gone away
1140
+ * never drains, and that must not hold the response open.
1141
+ */
1142
+ TERMINAL_DRAIN_TIMEOUT_MS: 5e3,
1099
1143
  /** Maximum active sessions in the cache */
1100
1144
  MAX_SESSIONS: 500,
1101
1145
  /** Background sweep interval for stale sessions (ms) */
@@ -1997,29 +2041,219 @@ var METADATA_FILES = new Set(
1997
2041
  );
1998
2042
 
1999
2043
  // ../../packages/core/src/proxy-settings.ts
2000
- var PROXY_SIZE_RE = /^[1-9][0-9]*(k|m|g)$/;
2044
+ var PROXY_SIZE_RE = /^(0|[1-9][0-9]*(k|m|g))$/;
2001
2045
  var PROXY_TIME_RE = /^[1-9][0-9]*(s|m|h)$/;
2046
+ var PROXY_BUFFERS_RE = /^[1-9][0-9]* [1-9][0-9]*(k|m|g)?$/;
2002
2047
  var PROXY_GZIP_TYPES = "text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml";
2003
- var PROXY_STRING_FIELD_RE = {
2004
- clientMaxBodySize: PROXY_SIZE_RE,
2005
- proxyReadTimeout: PROXY_TIME_RE,
2006
- proxySendTimeout: PROXY_TIME_RE,
2007
- clientBodyTimeout: PROXY_TIME_RE
2008
- };
2048
+ var PROXY_DIRECTIVES = [
2049
+ // ── Request body ────────────────────────────────────────────────────────
2050
+ { key: "clientMaxBodySize", directive: "client_max_body_size", kind: "size", group: "body" },
2051
+ { key: "clientBodyTimeout", directive: "client_body_timeout", kind: "time", group: "body" },
2052
+ {
2053
+ key: "clientBodyBufferSize",
2054
+ directive: "client_body_buffer_size",
2055
+ kind: "size",
2056
+ group: "body"
2057
+ },
2058
+ {
2059
+ key: "proxyRequestBuffering",
2060
+ directive: "proxy_request_buffering",
2061
+ kind: "bool",
2062
+ group: "body"
2063
+ },
2064
+ // ── Upstream timeouts ───────────────────────────────────────────────────
2065
+ { key: "proxyConnectTimeout", directive: "proxy_connect_timeout", kind: "time", group: "timeouts" },
2066
+ { key: "proxyReadTimeout", directive: "proxy_read_timeout", kind: "time", group: "timeouts" },
2067
+ { key: "proxySendTimeout", directive: "proxy_send_timeout", kind: "time", group: "timeouts" },
2068
+ { key: "sendTimeout", directive: "send_timeout", kind: "time", group: "timeouts" },
2069
+ { key: "keepaliveTimeout", directive: "keepalive_timeout", kind: "time", group: "timeouts" },
2070
+ // ── Response buffering ──────────────────────────────────────────────────
2071
+ { key: "proxyBuffering", directive: "proxy_buffering", kind: "bool", group: "buffering" },
2072
+ { key: "proxyBufferSize", directive: "proxy_buffer_size", kind: "size", group: "buffering" },
2073
+ { key: "proxyBuffers", directive: "proxy_buffers", kind: "buffers", group: "buffering" },
2074
+ {
2075
+ key: "proxyBusyBuffersSize",
2076
+ directive: "proxy_busy_buffers_size",
2077
+ kind: "size",
2078
+ group: "buffering"
2079
+ },
2080
+ {
2081
+ key: "proxyMaxTempFileSize",
2082
+ directive: "proxy_max_temp_file_size",
2083
+ kind: "size",
2084
+ group: "buffering"
2085
+ },
2086
+ // ── Compression ─────────────────────────────────────────────────────────
2087
+ {
2088
+ key: "gzip",
2089
+ directive: "gzip",
2090
+ kind: "bool",
2091
+ group: "compression",
2092
+ companionsWhenOn: [
2093
+ `gzip_types ${PROXY_GZIP_TYPES}`,
2094
+ "gzip_vary on",
2095
+ // nginx's own default is 20 bytes, small enough that the gzip header costs
2096
+ // more than the compression saves.
2097
+ "gzip_min_length 1024"
2098
+ ]
2099
+ },
2100
+ {
2101
+ key: "gzipCompLevel",
2102
+ directive: "gzip_comp_level",
2103
+ kind: "int",
2104
+ group: "compression",
2105
+ min: 1,
2106
+ max: 9
2107
+ },
2108
+ // Bytes, as an int — the natural unit here is "1024", and `size` would force "1k".
2109
+ {
2110
+ key: "gzipMinLength",
2111
+ directive: "gzip_min_length",
2112
+ kind: "int",
2113
+ group: "compression",
2114
+ min: 0,
2115
+ max: 10485760
2116
+ },
2117
+ // ── Headers & limits ────────────────────────────────────────────────────
2118
+ {
2119
+ key: "largeClientHeaderBuffers",
2120
+ directive: "large_client_header_buffers",
2121
+ kind: "buffers",
2122
+ group: "headers"
2123
+ },
2124
+ {
2125
+ key: "underscoresInHeaders",
2126
+ directive: "underscores_in_headers",
2127
+ kind: "bool",
2128
+ group: "headers"
2129
+ },
2130
+ { key: "serverTokens", directive: "server_tokens", kind: "bool", group: "headers" },
2131
+ {
2132
+ key: "http2",
2133
+ directive: "http2",
2134
+ kind: "bool",
2135
+ group: "headers",
2136
+ // `http2 on;` at server scope replaced `listen ... http2` in nginx 1.25.1.
2137
+ minNginx: [1, 25, 1],
2138
+ tlsOnly: true
2139
+ },
2140
+ // ── TLS to the upstream ─────────────────────────────────────────────────
2141
+ {
2142
+ key: "proxySslServerName",
2143
+ directive: "proxy_ssl_server_name",
2144
+ kind: "bool",
2145
+ group: "upstreamTls"
2146
+ },
2147
+ { key: "proxySslVerify", directive: "proxy_ssl_verify", kind: "bool", group: "upstreamTls" }
2148
+ ];
2149
+ var PROXY_DIRECTIVE_BY_KEY = new Map(
2150
+ PROXY_DIRECTIVES.map((d) => [d.key, d])
2151
+ );
2152
+ var PROXY_DIRECTIVE_BY_NAME = new Map(
2153
+ PROXY_DIRECTIVES.map((d) => [d.directive, d])
2154
+ );
2155
+ function proxyKindRegex(kind) {
2156
+ switch (kind) {
2157
+ case "size":
2158
+ return PROXY_SIZE_RE;
2159
+ case "time":
2160
+ return PROXY_TIME_RE;
2161
+ case "buffers":
2162
+ return PROXY_BUFFERS_RE;
2163
+ default:
2164
+ return void 0;
2165
+ }
2166
+ }
2167
+ var PROXY_STRING_FIELD_RE = Object.freeze(
2168
+ Object.fromEntries(
2169
+ PROXY_DIRECTIVES.flatMap((d) => {
2170
+ const re = proxyKindRegex(d.kind);
2171
+ return re ? [[d.key, re]] : [];
2172
+ })
2173
+ )
2174
+ );
2175
+ function coerceProxyValue(spec, value) {
2176
+ if (spec.kind === "bool") return typeof value === "boolean" ? value : void 0;
2177
+ if (spec.kind === "int") {
2178
+ if (typeof value !== "number" || !Number.isInteger(value)) return void 0;
2179
+ if (spec.min !== void 0 && value < spec.min) return void 0;
2180
+ if (spec.max !== void 0 && value > spec.max) return void 0;
2181
+ return value;
2182
+ }
2183
+ const re = proxyKindRegex(spec.kind);
2184
+ if (typeof value !== "string" || !re || !re.test(value)) return void 0;
2185
+ return value;
2186
+ }
2009
2187
  function sanitizeProxySettings(input) {
2010
2188
  if (!input || typeof input !== "object") return void 0;
2011
2189
  const src = input;
2012
2190
  const out = {};
2013
- for (const [key, re] of Object.entries(PROXY_STRING_FIELD_RE)) {
2014
- const v = src[key];
2015
- if (typeof v === "string" && re.test(v)) {
2016
- out[key] = v;
2017
- }
2191
+ for (const spec of PROXY_DIRECTIVES) {
2192
+ if (!(spec.key in src)) continue;
2193
+ const v = coerceProxyValue(spec, src[spec.key]);
2194
+ if (v !== void 0) out[spec.key] = v;
2018
2195
  }
2019
- if (typeof src.proxyBuffering === "boolean") out.proxyBuffering = src.proxyBuffering;
2020
- if (typeof src.gzip === "boolean") out.gzip = src.gzip;
2021
2196
  return Object.keys(out).length > 0 ? out : void 0;
2022
2197
  }
2198
+ function renderProxyValue(spec, value) {
2199
+ if (spec.kind === "bool") return value ? "on" : "off";
2200
+ return String(value);
2201
+ }
2202
+ function proxyDirectiveAllowed(spec, version2) {
2203
+ if (!spec.minNginx || !version2) return true;
2204
+ for (let i = 0; i < 3; i++) {
2205
+ const need = spec.minNginx[i] ?? 0;
2206
+ const have = version2[i] ?? 0;
2207
+ if (have > need) return true;
2208
+ if (have < need) return false;
2209
+ }
2210
+ return true;
2211
+ }
2212
+ function resolveProxyDirectives(settings, opts) {
2213
+ const p = sanitizeProxySettings(settings);
2214
+ if (!p) return [];
2215
+ const values = p;
2216
+ const explicit = new Set(
2217
+ PROXY_DIRECTIVES.filter((s) => values[s.key] !== void 0).map((s) => s.directive)
2218
+ );
2219
+ const out = [];
2220
+ for (const spec of PROXY_DIRECTIVES) {
2221
+ const wanted = opts.scope === "all" || opts.scope === "tls" === !!spec.tlsOnly;
2222
+ if (!wanted) continue;
2223
+ if (!proxyDirectiveAllowed(spec, opts.nginxVersion)) continue;
2224
+ const value = values[spec.key];
2225
+ if (value === void 0) continue;
2226
+ out.push({ directive: spec.directive, text: renderProxyValue(spec, value), key: spec.key, value });
2227
+ if (value !== true || !spec.companionsWhenOn) continue;
2228
+ for (const line of spec.companionsWhenOn) {
2229
+ const [name, ...rest] = line.split(/\s+/);
2230
+ if (!name || explicit.has(name)) continue;
2231
+ const text = rest.join(" ");
2232
+ const companion = PROXY_DIRECTIVE_BY_NAME.get(name);
2233
+ const parsed = companion ? parseProxyValue(companion, text) : void 0;
2234
+ out.push({
2235
+ directive: name,
2236
+ text,
2237
+ ...companion && parsed !== void 0 ? { key: companion.key, value: parsed } : {}
2238
+ });
2239
+ }
2240
+ }
2241
+ return out;
2242
+ }
2243
+ function parseProxyValue(spec, raw) {
2244
+ const text = raw.trim();
2245
+ if (spec.kind === "bool") {
2246
+ if (text === "on") return true;
2247
+ if (text === "off") return false;
2248
+ return void 0;
2249
+ }
2250
+ if (spec.kind === "int") {
2251
+ if (!/^[0-9]+$/.test(text)) return void 0;
2252
+ return coerceProxyValue(spec, Number(text));
2253
+ }
2254
+ const normalized = spec.kind === "buffers" ? text.replace(/\s+/g, " ") : text;
2255
+ return coerceProxyValue(spec, normalized.toLowerCase());
2256
+ }
2023
2257
 
2024
2258
  // ../../packages/core/src/object-storage.ts
2025
2259
  function isAwsS3Endpoint(endpoint2) {
@@ -2074,6 +2308,15 @@ function commandToArgv(command) {
2074
2308
  return shellSplitWords(command);
2075
2309
  }
2076
2310
 
2311
+ // ../../packages/core/src/mail-image-ref.ts
2312
+ function buildMailImageRef(opts) {
2313
+ return buildImageRef(opts, {
2314
+ name: "openship-mail",
2315
+ imageOverride: process.env.OPENSHIP_MAIL_IMAGE,
2316
+ tagOverride: process.env.OPENSHIP_MAIL_TAG
2317
+ });
2318
+ }
2319
+
2077
2320
  // ../../packages/core/src/runtime-config.ts
2078
2321
  var DEFAULT_PORT = {
2079
2322
  web: 3e3,
@@ -2972,9 +3215,6 @@ var catalog_default = {
2972
3215
  {
2973
3216
  name: "db",
2974
3217
  image: "supabase/postgres:17.6.1.136",
2975
- ports: [
2976
- "5432:5432"
2977
- ],
2978
3218
  environment: {
2979
3219
  POSTGRES_HOST: "/var/run/postgresql",
2980
3220
  PGPORT: "5432",
@@ -2985,7 +3225,8 @@ var catalog_default = {
2985
3225
  JWT_EXP: "3600"
2986
3226
  },
2987
3227
  volumes: [
2988
- "supabase_db_data:/var/lib/postgresql/data"
3228
+ "supabase_db_data:/var/lib/postgresql/data",
3229
+ "supabase_db_config:/etc/postgresql-custom"
2989
3230
  ],
2990
3231
  healthcheck: {
2991
3232
  test: [
@@ -3005,9 +3246,6 @@ var catalog_default = {
3005
3246
  {
3006
3247
  name: "kong",
3007
3248
  image: "kong:3.9.1",
3008
- ports: [
3009
- "8000:8000"
3010
- ],
3011
3249
  exposedPort: 8e3,
3012
3250
  exposed: true,
3013
3251
  routes: [
@@ -3161,7 +3399,7 @@ var catalog_default = {
3161
3399
  "--no-verbose",
3162
3400
  "--tries=1",
3163
3401
  "--spider",
3164
- "http://localhost:5000/status"
3402
+ "http://127.0.0.1:5000/status"
3165
3403
  ],
3166
3404
  interval: "5s",
3167
3405
  timeout: "5s",
@@ -3314,8 +3552,231 @@ var catalog_default = {
3314
3552
  },
3315
3553
  {
3316
3554
  service: "db",
3317
- path: "/docker-entrypoint-initdb.d/99-roles.sql",
3318
- content: "ALTER USER authenticator WITH PASSWORD '{{config:POSTGRES_PASSWORD}}';\nALTER USER pgbouncer WITH PASSWORD '{{config:POSTGRES_PASSWORD}}';\nALTER USER supabase_auth_admin WITH PASSWORD '{{config:POSTGRES_PASSWORD}}';\nALTER USER supabase_functions_admin WITH PASSWORD '{{config:POSTGRES_PASSWORD}}';\nALTER USER supabase_storage_admin WITH PASSWORD '{{config:POSTGRES_PASSWORD}}';\nALTER USER supabase_admin WITH PASSWORD '{{config:POSTGRES_PASSWORD}}';\n"
3555
+ path: "/docker-entrypoint-initdb.d/init-scripts/98-webhooks.sql",
3556
+ content: `BEGIN;
3557
+ -- Create pg_net extension
3558
+ CREATE EXTENSION IF NOT EXISTS pg_net SCHEMA extensions;
3559
+ -- Create supabase_functions schema
3560
+ CREATE SCHEMA supabase_functions AUTHORIZATION supabase_admin;
3561
+ GRANT USAGE ON SCHEMA supabase_functions TO postgres, anon, authenticated, service_role;
3562
+ ALTER DEFAULT PRIVILEGES IN SCHEMA supabase_functions GRANT ALL ON TABLES TO postgres, anon, authenticated, service_role;
3563
+ ALTER DEFAULT PRIVILEGES IN SCHEMA supabase_functions GRANT ALL ON FUNCTIONS TO postgres, anon, authenticated, service_role;
3564
+ ALTER DEFAULT PRIVILEGES IN SCHEMA supabase_functions GRANT ALL ON SEQUENCES TO postgres, anon, authenticated, service_role;
3565
+ -- supabase_functions.migrations definition
3566
+ CREATE TABLE supabase_functions.migrations (
3567
+ version text PRIMARY KEY,
3568
+ inserted_at timestamptz NOT NULL DEFAULT NOW()
3569
+ );
3570
+ -- Initial supabase_functions migration
3571
+ INSERT INTO supabase_functions.migrations (version) VALUES ('initial');
3572
+ -- supabase_functions.hooks definition
3573
+ CREATE TABLE supabase_functions.hooks (
3574
+ id bigserial PRIMARY KEY,
3575
+ hook_table_id integer NOT NULL,
3576
+ hook_name text NOT NULL,
3577
+ created_at timestamptz NOT NULL DEFAULT NOW(),
3578
+ request_id bigint
3579
+ );
3580
+ CREATE INDEX supabase_functions_hooks_request_id_idx ON supabase_functions.hooks USING btree (request_id);
3581
+ CREATE INDEX supabase_functions_hooks_h_table_id_h_name_idx ON supabase_functions.hooks USING btree (hook_table_id, hook_name);
3582
+ COMMENT ON TABLE supabase_functions.hooks IS 'Supabase Functions Hooks: Audit trail for triggered hooks.';
3583
+ CREATE FUNCTION supabase_functions.http_request()
3584
+ RETURNS trigger
3585
+ LANGUAGE plpgsql
3586
+ AS $function$
3587
+ DECLARE
3588
+ request_id bigint;
3589
+ payload jsonb;
3590
+ url text := TG_ARGV[0]::text;
3591
+ method text := TG_ARGV[1]::text;
3592
+ headers jsonb DEFAULT '{}'::jsonb;
3593
+ params jsonb DEFAULT '{}'::jsonb;
3594
+ timeout_ms integer DEFAULT 1000;
3595
+ BEGIN
3596
+ IF url IS NULL OR url = 'null' THEN
3597
+ RAISE EXCEPTION 'url argument is missing';
3598
+ END IF;
3599
+
3600
+ IF method IS NULL OR method = 'null' THEN
3601
+ RAISE EXCEPTION 'method argument is missing';
3602
+ END IF;
3603
+
3604
+ IF TG_ARGV[2] IS NULL OR TG_ARGV[2] = 'null' THEN
3605
+ headers = '{"Content-Type": "application/json"}'::jsonb;
3606
+ ELSE
3607
+ headers = TG_ARGV[2]::jsonb;
3608
+ END IF;
3609
+
3610
+ IF TG_ARGV[3] IS NULL OR TG_ARGV[3] = 'null' THEN
3611
+ params = '{}'::jsonb;
3612
+ ELSE
3613
+ params = TG_ARGV[3]::jsonb;
3614
+ END IF;
3615
+
3616
+ IF TG_ARGV[4] IS NULL OR TG_ARGV[4] = 'null' THEN
3617
+ timeout_ms = 1000;
3618
+ ELSE
3619
+ timeout_ms = TG_ARGV[4]::integer;
3620
+ END IF;
3621
+
3622
+ CASE
3623
+ WHEN method = 'GET' THEN
3624
+ SELECT http_get INTO request_id FROM net.http_get(
3625
+ url,
3626
+ params,
3627
+ headers,
3628
+ timeout_ms
3629
+ );
3630
+ WHEN method = 'POST' THEN
3631
+ payload = jsonb_build_object(
3632
+ 'old_record', OLD,
3633
+ 'record', NEW,
3634
+ 'type', TG_OP,
3635
+ 'table', TG_TABLE_NAME,
3636
+ 'schema', TG_TABLE_SCHEMA
3637
+ );
3638
+
3639
+ SELECT http_post INTO request_id FROM net.http_post(
3640
+ url,
3641
+ payload,
3642
+ params,
3643
+ headers,
3644
+ timeout_ms
3645
+ );
3646
+ ELSE
3647
+ RAISE EXCEPTION 'method argument % is invalid', method;
3648
+ END CASE;
3649
+
3650
+ INSERT INTO supabase_functions.hooks
3651
+ (hook_table_id, hook_name, request_id)
3652
+ VALUES
3653
+ (TG_RELID, TG_NAME, request_id);
3654
+
3655
+ RETURN NEW;
3656
+ END
3657
+ $function$;
3658
+ -- Supabase super admin
3659
+ DO
3660
+ $$
3661
+ BEGIN
3662
+ IF NOT EXISTS (
3663
+ SELECT 1
3664
+ FROM pg_roles
3665
+ WHERE rolname = 'supabase_functions_admin'
3666
+ )
3667
+ THEN
3668
+ CREATE USER supabase_functions_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION;
3669
+ END IF;
3670
+ END
3671
+ $$;
3672
+ GRANT ALL PRIVILEGES ON SCHEMA supabase_functions TO supabase_functions_admin;
3673
+ GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA supabase_functions TO supabase_functions_admin;
3674
+ GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA supabase_functions TO supabase_functions_admin;
3675
+ ALTER USER supabase_functions_admin SET search_path = "supabase_functions";
3676
+ ALTER table "supabase_functions".migrations OWNER TO supabase_functions_admin;
3677
+ ALTER table "supabase_functions".hooks OWNER TO supabase_functions_admin;
3678
+ ALTER function "supabase_functions".http_request() OWNER TO supabase_functions_admin;
3679
+ GRANT supabase_functions_admin TO postgres;
3680
+ -- Remove unused supabase_pg_net_admin role
3681
+ DO
3682
+ $$
3683
+ BEGIN
3684
+ IF EXISTS (
3685
+ SELECT 1
3686
+ FROM pg_roles
3687
+ WHERE rolname = 'supabase_pg_net_admin'
3688
+ )
3689
+ THEN
3690
+ REASSIGN OWNED BY supabase_pg_net_admin TO supabase_admin;
3691
+ DROP OWNED BY supabase_pg_net_admin;
3692
+ DROP ROLE supabase_pg_net_admin;
3693
+ END IF;
3694
+ END
3695
+ $$;
3696
+ -- pg_net grants when extension is already enabled
3697
+ DO
3698
+ $$
3699
+ BEGIN
3700
+ IF EXISTS (
3701
+ SELECT 1
3702
+ FROM pg_extension
3703
+ WHERE extname = 'pg_net'
3704
+ )
3705
+ THEN
3706
+ GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role;
3707
+ ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
3708
+ ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
3709
+ ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
3710
+ ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
3711
+ REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
3712
+ REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
3713
+ GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
3714
+ GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
3715
+ END IF;
3716
+ END
3717
+ $$;
3718
+ -- Event trigger for pg_net
3719
+ CREATE OR REPLACE FUNCTION extensions.grant_pg_net_access()
3720
+ RETURNS event_trigger
3721
+ LANGUAGE plpgsql
3722
+ AS $$
3723
+ BEGIN
3724
+ IF EXISTS (
3725
+ SELECT 1
3726
+ FROM pg_event_trigger_ddl_commands() AS ev
3727
+ JOIN pg_extension AS ext
3728
+ ON ev.objid = ext.oid
3729
+ WHERE ext.extname = 'pg_net'
3730
+ )
3731
+ THEN
3732
+ GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role;
3733
+ ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
3734
+ ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
3735
+ ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
3736
+ ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
3737
+ REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
3738
+ REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
3739
+ GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
3740
+ GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
3741
+ END IF;
3742
+ END;
3743
+ $$;
3744
+ COMMENT ON FUNCTION extensions.grant_pg_net_access IS 'Grants access to pg_net';
3745
+ DO
3746
+ $$
3747
+ BEGIN
3748
+ IF NOT EXISTS (
3749
+ SELECT 1
3750
+ FROM pg_event_trigger
3751
+ WHERE evtname = 'issue_pg_net_access'
3752
+ ) THEN
3753
+ CREATE EVENT TRIGGER issue_pg_net_access ON ddl_command_end WHEN TAG IN ('CREATE EXTENSION')
3754
+ EXECUTE PROCEDURE extensions.grant_pg_net_access();
3755
+ END IF;
3756
+ END
3757
+ $$;
3758
+ INSERT INTO supabase_functions.migrations (version) VALUES ('20210809183423_update_grants');
3759
+ ALTER function supabase_functions.http_request() SECURITY DEFINER;
3760
+ ALTER function supabase_functions.http_request() SET search_path = supabase_functions;
3761
+ REVOKE ALL ON FUNCTION supabase_functions.http_request() FROM PUBLIC;
3762
+ GRANT EXECUTE ON FUNCTION supabase_functions.http_request() TO postgres, anon, authenticated, service_role;
3763
+ COMMIT;
3764
+ `
3765
+ },
3766
+ {
3767
+ service: "db",
3768
+ path: "/docker-entrypoint-initdb.d/init-scripts/99-jwt.sql",
3769
+ content: '\\set jwt_secret `echo "$JWT_SECRET"`\n\\set jwt_exp `echo "$JWT_EXP"`\n\nALTER DATABASE postgres SET "app.settings.jwt_secret" TO :\'jwt_secret\';\nALTER DATABASE postgres SET "app.settings.jwt_exp" TO :\'jwt_exp\';\n'
3770
+ },
3771
+ {
3772
+ service: "db",
3773
+ path: "/docker-entrypoint-initdb.d/init-scripts/99-roles.sql",
3774
+ content: "\\set pgpass `echo \"$POSTGRES_PASSWORD\"`\n\nALTER USER authenticator WITH PASSWORD :'pgpass';\nALTER USER pgbouncer WITH PASSWORD :'pgpass';\nALTER USER supabase_auth_admin WITH PASSWORD :'pgpass';\nALTER USER supabase_functions_admin WITH PASSWORD :'pgpass';\nALTER USER supabase_storage_admin WITH PASSWORD :'pgpass';\n"
3775
+ },
3776
+ {
3777
+ service: "db",
3778
+ path: "/docker-entrypoint-initdb.d/migrations/99-realtime.sql",
3779
+ content: '\\set pguser `echo "$POSTGRES_USER"`\n\ncreate schema if not exists _realtime;\nalter schema _realtime owner to :pguser;\n'
3319
3780
  }
3320
3781
  ],
3321
3782
  management: {
@@ -3340,6 +3801,7 @@ var catalog_default = {
3340
3801
  id: "studio",
3341
3802
  label: "Studio",
3342
3803
  source: "publicUrl:kong",
3804
+ kind: "url",
3343
3805
  help: "Open in a browser and sign in with the Studio username + password below."
3344
3806
  },
3345
3807
  {
@@ -3370,12 +3832,12 @@ var catalog_default = {
3370
3832
  {
3371
3833
  id: "dbUrl",
3372
3834
  label: "Database URL",
3373
- source: "template:postgresql://postgres:{{env:db:POSTGRES_PASSWORD}}@{{host}}:5432/postgres",
3835
+ source: "template:postgresql://postgres:{{env:db:POSTGRES_PASSWORD}}@db:5432/postgres",
3374
3836
  service: "db",
3375
3837
  secret: true,
3376
3838
  envKey: "DATABASE_URL",
3377
3839
  recommended: true,
3378
- help: "Direct Postgres connection (superuser) for psql / ORMs. Published on port 5432."
3840
+ help: "Direct Postgres connection (superuser) reachable over this project's shared network. Connect another project to Supabase to inject it automatically."
3379
3841
  },
3380
3842
  {
3381
3843
  id: "dbPassword",
@@ -3397,7 +3859,8 @@ var catalog_default = {
3397
3859
  service: "db",
3398
3860
  port: 5432,
3399
3861
  label: "Database",
3400
- kind: "tcp"
3862
+ kind: "tcp",
3863
+ scope: "internal"
3401
3864
  }
3402
3865
  ],
3403
3866
  settings: [
@@ -3490,12 +3953,8 @@ var catalog_default = {
3490
3953
  },
3491
3954
  healthcheck: {
3492
3955
  test: [
3493
- "CMD",
3494
- "wget",
3495
- "--no-verbose",
3496
- "--tries=1",
3497
- "--spider",
3498
- "http://localhost:8081/"
3956
+ "CMD-SHELL",
3957
+ 'wget -q -S --spider http://127.0.0.1:8081/ 2>&1 | grep -q "HTTP/"'
3499
3958
  ],
3500
3959
  interval: "10s",
3501
3960
  timeout: "5s",
@@ -3539,6 +3998,7 @@ var catalog_default = {
3539
3998
  id: "admin",
3540
3999
  label: "Mongo Express",
3541
4000
  source: "publicUrl:mongo-express",
4001
+ kind: "url",
3542
4002
  envKey: "MONGO_EXPRESS_URL",
3543
4003
  help: "Sign in with the username + password below."
3544
4004
  },
@@ -3597,6 +4057,7 @@ var catalog_default = {
3597
4057
  id: "convex",
3598
4058
  name: "Convex",
3599
4059
  description: "Self-hosted Convex reactive backend + dashboard, with a persistent data volume.",
4060
+ repository: "https://github.com/get-convex/convex-backend",
3600
4061
  kind: "template",
3601
4062
  logo: "convex",
3602
4063
  category: "backend",
@@ -3609,7 +4070,7 @@ var catalog_default = {
3609
4070
  services: [
3610
4071
  {
3611
4072
  name: "backend",
3612
- image: "ghcr.io/get-convex/convex-backend:latest",
4073
+ image: "ghcr.io/get-convex/convex-backend:19431ea0dd90bc55ae58dbbd06d9aa045f97336f",
3613
4074
  ports: [
3614
4075
  "3210:3210",
3615
4076
  "3211:3211"
@@ -3651,7 +4112,7 @@ var catalog_default = {
3651
4112
  },
3652
4113
  {
3653
4114
  name: "dashboard",
3654
- image: "ghcr.io/get-convex/convex-dashboard:latest",
4115
+ image: "ghcr.io/get-convex/convex-dashboard:19431ea0dd90bc55ae58dbbd06d9aa045f97336f",
3655
4116
  ports: [
3656
4117
  "6791:6791"
3657
4118
  ],
@@ -3684,21 +4145,32 @@ var catalog_default = {
3684
4145
  service: "backend",
3685
4146
  command: "./generate_admin_key.sh",
3686
4147
  capture: "adminKey",
3687
- capturePattern: "Admin key:\\s*(\\S+)",
4148
+ capturePattern: "([^\\r\\n]+)\\s*$",
3688
4149
  persistAs: {
3689
4150
  key: "CONVEX_ADMIN_KEY"
3690
4151
  },
3691
- once: true
4152
+ once: true,
4153
+ title: "Generate admin key",
4154
+ description: "Mint the dashboard and CLI admin key from the instance secret.",
4155
+ icon: "key"
3692
4156
  }
3693
4157
  ],
3694
4158
  connection: {
3695
4159
  title: "Connect to this deployment",
3696
4160
  description: "Sign in to the Convex dashboard, or point the Convex CLI here, with these values.",
3697
4161
  outputs: [
4162
+ {
4163
+ id: "dashboard",
4164
+ label: "Dashboard URL",
4165
+ source: "publicUrl:dashboard",
4166
+ kind: "url",
4167
+ help: "Open the Convex dashboard UI, then sign in with the deployment URL and admin key below."
4168
+ },
3698
4169
  {
3699
4170
  id: "url",
3700
4171
  label: "Deployment URL",
3701
- source: "env:backend:CONVEX_CLOUD_ORIGIN"
4172
+ source: "env:backend:CONVEX_CLOUD_ORIGIN",
4173
+ kind: "url"
3702
4174
  },
3703
4175
  {
3704
4176
  id: "adminKey",
@@ -4077,7 +4549,23 @@ var catalog_default = {
4077
4549
  ],
4078
4550
  restart: "unless-stopped"
4079
4551
  }
4080
- ]
4552
+ ],
4553
+ connection: {
4554
+ title: "Sign in to Grafana",
4555
+ outputs: [
4556
+ {
4557
+ id: "url",
4558
+ label: "URL",
4559
+ source: "publicUrl:grafana",
4560
+ kind: "url"
4561
+ }
4562
+ ],
4563
+ firstLogin: {
4564
+ username: "admin",
4565
+ password: "admin",
4566
+ note: "Change the admin password right after your first login."
4567
+ }
4568
+ }
4081
4569
  },
4082
4570
  {
4083
4571
  available: false,
@@ -4463,7 +4951,8 @@ var catalog_default = {
4463
4951
  {
4464
4952
  id: "console",
4465
4953
  label: "Console",
4466
- source: "publicUrl:minio:9001"
4954
+ source: "publicUrl:minio:9001",
4955
+ kind: "url"
4467
4956
  },
4468
4957
  {
4469
4958
  id: "endpoint",
@@ -4609,6 +5098,7 @@ var catalog_default = {
4609
5098
  id: "ui",
4610
5099
  label: "Kafka UI",
4611
5100
  source: "publicUrl:kafka-ui",
5101
+ kind: "url",
4612
5102
  help: "Sign in with the username + password below."
4613
5103
  },
4614
5104
  {
@@ -4701,6 +5191,7 @@ var catalog_default = {
4701
5191
  id: "ui",
4702
5192
  label: "Qdrant Web UI",
4703
5193
  source: "publicUrl:qdrant",
5194
+ kind: "url",
4704
5195
  help: "The dashboard is at this URL under /dashboard. Paste the API key when it asks."
4705
5196
  },
4706
5197
  {
@@ -19287,6 +19778,7 @@ var configField = external_exports.object({
19287
19778
  required: external_exports.boolean().optional(),
19288
19779
  secret: external_exports.boolean().optional()
19289
19780
  });
19781
+ var localized = external_exports.union([external_exports.string(), external_exports.record(external_exports.string(), external_exports.string())]);
19290
19782
  var prepareStep = external_exports.object({
19291
19783
  service: external_exports.string(),
19292
19784
  command: external_exports.string(),
@@ -19296,7 +19788,12 @@ var prepareStep = external_exports.object({
19296
19788
  once: external_exports.boolean().optional(),
19297
19789
  phase: external_exports.enum(["pre-deploy", "post-start", "post-ready"]).optional(),
19298
19790
  mustSucceed: external_exports.boolean().optional(),
19299
- readiness: external_exports.object({ test: external_exports.string(), interval: external_exports.number().optional(), retries: external_exports.number().optional() }).optional()
19791
+ readiness: external_exports.object({ test: external_exports.string(), interval: external_exports.number().optional(), retries: external_exports.number().optional() }).optional(),
19792
+ // Authored display copy for the install stepper's "app-setup" sub-steps. Purely
19793
+ // presentational; absent → the renderer uses a generic label.
19794
+ title: localized.optional(),
19795
+ description: localized.optional(),
19796
+ icon: external_exports.string().optional()
19300
19797
  });
19301
19798
  var outputVariant = external_exports.object({
19302
19799
  id: external_exports.string(),
@@ -19321,7 +19818,11 @@ var connection = external_exports.object({
19321
19818
  recommended: external_exports.boolean().optional(),
19322
19819
  sourceLabel: external_exports.union([external_exports.string(), external_exports.record(external_exports.string(), external_exports.string())]).optional(),
19323
19820
  variants: external_exports.array(outputVariant).optional(),
19324
- width: external_exports.enum(["full", "half"]).optional()
19821
+ width: external_exports.enum(["full", "half"]).optional(),
19822
+ /** "url" marks the resolved value as an openable link — the Connection
19823
+ * card shows an Open-in-new-tab action beside it. Enforced only for a
19824
+ * resolved http(s) value (checked at render); default "text". Additive. */
19825
+ kind: external_exports.enum(["text", "url"]).optional()
19325
19826
  })
19326
19827
  ),
19327
19828
  guide: external_exports.object({
@@ -19329,6 +19830,14 @@ var connection = external_exports.object({
19329
19830
  intro: external_exports.union([external_exports.string(), external_exports.record(external_exports.string(), external_exports.string())]).optional(),
19330
19831
  useHint: external_exports.union([external_exports.string(), external_exports.record(external_exports.string(), external_exports.string())]).optional(),
19331
19832
  defaultMode: external_exports.enum(["internal", "public"]).optional()
19833
+ }).optional(),
19834
+ // Static default credentials the app ships with (e.g. Grafana admin/admin).
19835
+ // These are FIXED values, not derived from a service env, so they can't live in
19836
+ // `outputs` (whose values resolve from running services) — hence their own field.
19837
+ firstLogin: external_exports.object({
19838
+ username: localized.optional(),
19839
+ password: localized.optional(),
19840
+ note: localized.optional()
19332
19841
  }).optional()
19333
19842
  });
19334
19843
  var endpointMode = external_exports.enum(["domain", "port", "publish", "internal"]);
@@ -19342,7 +19851,6 @@ var endpoint = external_exports.object({
19342
19851
  defaultMode: endpointMode.optional(),
19343
19852
  allowedModes: external_exports.array(endpointMode).optional()
19344
19853
  });
19345
- var localized = external_exports.union([external_exports.string(), external_exports.record(external_exports.string(), external_exports.string())]);
19346
19854
  var provides = external_exports.object({
19347
19855
  id: external_exports.string(),
19348
19856
  outputRefs: external_exports.array(external_exports.string()),
@@ -19427,7 +19935,8 @@ var appTemplateSchema = external_exports.object({
19427
19935
  // Versioning / compat gate (see parseAppTemplate).
19428
19936
  schemaVersion: external_exports.number().optional(),
19429
19937
  minEngine: external_exports.string().optional(),
19430
- updatedAt: external_exports.string().optional()
19938
+ updatedAt: external_exports.string().optional(),
19939
+ repository: external_exports.string().url().optional()
19431
19940
  }).superRefine((data, ctx) => {
19432
19941
  const svcNames = new Set((data.services ?? []).map((s) => s.name));
19433
19942
  const refSvc = (service, path, where) => {
@@ -19490,6 +19999,757 @@ function cliInstallCommand(pm, version2) {
19490
19999
  return pm === "bun" ? `bun add -g ${ref}` : `npm install -g ${ref}`;
19491
20000
  }
19492
20001
 
20002
+ // ../../packages/core/src/audit-taxonomy.ts
20003
+ var AUDIT_CATEGORIES = [
20004
+ {
20005
+ id: "deployments",
20006
+ label: "Deployments",
20007
+ description: "Builds and releases \u2014 what shipped, what failed, what was cancelled."
20008
+ },
20009
+ {
20010
+ id: "apps",
20011
+ label: "Apps & services",
20012
+ description: "Projects, the services inside them, and their runtime health."
20013
+ },
20014
+ {
20015
+ id: "domains",
20016
+ label: "Domains & SSL",
20017
+ description: "Custom domains, DNS verification, and certificates."
20018
+ },
20019
+ {
20020
+ id: "servers",
20021
+ label: "Servers",
20022
+ description: "Deployment targets, their configuration, and shell access."
20023
+ },
20024
+ {
20025
+ id: "members",
20026
+ label: "Members & access",
20027
+ description: "Who is in this organization and what they are allowed to do."
20028
+ },
20029
+ {
20030
+ id: "security",
20031
+ label: "Security",
20032
+ description: "Admin credentials, auth mode, data export, and audit recording itself."
20033
+ },
20034
+ {
20035
+ id: "billing",
20036
+ label: "Billing",
20037
+ description: "Subscriptions, credits, spending caps, and quota thresholds."
20038
+ },
20039
+ {
20040
+ id: "system",
20041
+ label: "System",
20042
+ description: "Settings, integrations, notifications, backups, and instance maintenance."
20043
+ }
20044
+ ];
20045
+ var AUDIT_EVENTS = {
20046
+ /* ---------------- Deployments ---------------- */
20047
+ "deployment.succeeded": {
20048
+ category: "deployments",
20049
+ action: "deployed",
20050
+ label: "Deploy succeeded",
20051
+ tone: "success",
20052
+ description: "A deployment finished successfully and is serving traffic."
20053
+ },
20054
+ "deployment.failed": {
20055
+ category: "deployments",
20056
+ action: "failed to deploy",
20057
+ label: "Deploy failed",
20058
+ tone: "danger",
20059
+ description: "A deployment errored out before reaching a healthy state."
20060
+ },
20061
+ "deployment.cancelled": {
20062
+ category: "deployments",
20063
+ action: "cancelled the deploy of",
20064
+ label: "Deploy cancelled",
20065
+ tone: "warning",
20066
+ description: "A deployment was stopped before it finished."
20067
+ },
20068
+ "deployment:write": {
20069
+ category: "deployments",
20070
+ action: "started a deploy for",
20071
+ label: "Deploy action",
20072
+ description: "A deployment endpoint was invoked \u2014 start, retry, rollback, or promote."
20073
+ },
20074
+ "deployment:admin": {
20075
+ category: "deployments",
20076
+ action: "ran an admin action on the deploy for",
20077
+ label: "Deploy admin action",
20078
+ tone: "warning",
20079
+ description: "A destructive deployment endpoint was invoked, such as cancel or destroy."
20080
+ },
20081
+ /* ---------------- Apps & services ---------------- */
20082
+ "project.created": {
20083
+ category: "apps",
20084
+ action: "created",
20085
+ label: "App created",
20086
+ tone: "info"
20087
+ },
20088
+ "project.updated": {
20089
+ category: "apps",
20090
+ action: "updated",
20091
+ label: "App updated",
20092
+ description: "Settings, services, environment variables, or routing were changed."
20093
+ },
20094
+ "project.deleted": {
20095
+ category: "apps",
20096
+ action: "deleted",
20097
+ label: "App deleted",
20098
+ tone: "danger"
20099
+ },
20100
+ "project.deletion.rejected": {
20101
+ category: "apps",
20102
+ action: "tried to delete",
20103
+ label: "App deletion refused",
20104
+ tone: "warning",
20105
+ description: "A delete was refused \u2014 something still depends on this app."
20106
+ },
20107
+ "project:write": {
20108
+ category: "apps",
20109
+ action: "changed",
20110
+ label: "App changed",
20111
+ description: "One of the app's write endpoints was invoked."
20112
+ },
20113
+ "project:admin": {
20114
+ category: "apps",
20115
+ action: "ran an admin action on",
20116
+ label: "App admin action",
20117
+ tone: "warning",
20118
+ description: "A destructive app endpoint was invoked, such as delete or transfer."
20119
+ },
20120
+ "project:service:write": {
20121
+ category: "apps",
20122
+ action: "changed a service in",
20123
+ label: "Service changed",
20124
+ description: "A service was created, updated, started, stopped, or restarted."
20125
+ },
20126
+ "project:service:admin": {
20127
+ category: "apps",
20128
+ action: "ran an admin action on a service in",
20129
+ label: "Service admin action",
20130
+ tone: "warning"
20131
+ },
20132
+ "job:write": {
20133
+ category: "apps",
20134
+ action: "changed the job",
20135
+ label: "Job changed",
20136
+ description: "A scheduled or custom job was created, edited, run, or removed."
20137
+ },
20138
+ "job_run.started": {
20139
+ category: "apps",
20140
+ action: "started the job",
20141
+ label: "Job started"
20142
+ },
20143
+ "job_run.succeeded": {
20144
+ category: "apps",
20145
+ action: "ran the job",
20146
+ label: "Job succeeded",
20147
+ tone: "success"
20148
+ },
20149
+ "job_run.failed": {
20150
+ category: "apps",
20151
+ action: "ran the failing job",
20152
+ label: "Job failed",
20153
+ tone: "danger"
20154
+ },
20155
+ // Written by the health watcher, never by a person — these only ever render
20156
+ // through `label`.
20157
+ "service.down": {
20158
+ category: "apps",
20159
+ action: "reported down",
20160
+ label: "App went down",
20161
+ tone: "danger",
20162
+ description: "A container that should be running isn't \u2014 exited, dead, or OOM-killed."
20163
+ },
20164
+ "service.crash_loop": {
20165
+ category: "apps",
20166
+ action: "reported crash looping",
20167
+ label: "App is crash looping",
20168
+ tone: "danger",
20169
+ description: "A container keeps restarting instead of staying up."
20170
+ },
20171
+ "service.unhealthy": {
20172
+ category: "apps",
20173
+ action: "reported unhealthy",
20174
+ label: "App is unhealthy",
20175
+ tone: "warning",
20176
+ description: "A container is running but its own healthcheck is failing."
20177
+ },
20178
+ "service.recovered": {
20179
+ category: "apps",
20180
+ action: "reported recovered",
20181
+ label: "App recovered",
20182
+ tone: "success",
20183
+ description: "An outage ended and the container is healthy again."
20184
+ },
20185
+ /* ---------------- Domains & SSL ---------------- */
20186
+ "domain.added": {
20187
+ category: "domains",
20188
+ action: "added the domain",
20189
+ label: "Domain added",
20190
+ tone: "info"
20191
+ },
20192
+ "domain.removed": {
20193
+ category: "domains",
20194
+ action: "removed the domain",
20195
+ label: "Domain removed",
20196
+ tone: "danger"
20197
+ },
20198
+ "domain.verified": {
20199
+ category: "domains",
20200
+ action: "verified the domain",
20201
+ label: "Domain verified",
20202
+ tone: "success",
20203
+ description: "DNS verification succeeded, so the domain can be issued a certificate."
20204
+ },
20205
+ "domain.verification_failed": {
20206
+ category: "domains",
20207
+ action: "failed to verify the domain",
20208
+ label: "Domain verification failed",
20209
+ tone: "warning",
20210
+ description: "DNS records for this domain don't point here yet."
20211
+ },
20212
+ "domain.set_primary": {
20213
+ category: "domains",
20214
+ action: "made primary the domain",
20215
+ label: "Primary domain changed",
20216
+ description: "The domain other addresses now redirect to."
20217
+ },
20218
+ "domain.cert_uploaded": {
20219
+ category: "domains",
20220
+ action: "uploaded a certificate for",
20221
+ label: "Certificate uploaded",
20222
+ description: "A certificate and key were supplied by hand instead of issued automatically."
20223
+ },
20224
+ "ssl.renewal_failed": {
20225
+ category: "domains",
20226
+ action: "failed to renew SSL for",
20227
+ label: "SSL renewal failed",
20228
+ tone: "danger",
20229
+ description: "Automatic renewal failed \u2014 the certificate will expire unless this is fixed."
20230
+ },
20231
+ "domain:write": {
20232
+ category: "domains",
20233
+ action: "changed the domain",
20234
+ label: "Domain action",
20235
+ description: "A domain endpoint was invoked \u2014 add, verify, or renew."
20236
+ },
20237
+ "domain:admin": {
20238
+ category: "domains",
20239
+ action: "ran an admin action on the domain",
20240
+ label: "Domain admin action",
20241
+ tone: "warning"
20242
+ },
20243
+ /* ---------------- Servers ---------------- */
20244
+ "server.added": {
20245
+ category: "servers",
20246
+ action: "added the server",
20247
+ label: "Server added",
20248
+ tone: "info"
20249
+ },
20250
+ "server.updated": {
20251
+ category: "servers",
20252
+ action: "updated the server",
20253
+ label: "Server updated"
20254
+ },
20255
+ "server.removed": {
20256
+ category: "servers",
20257
+ action: "removed the server",
20258
+ label: "Server removed",
20259
+ tone: "danger"
20260
+ },
20261
+ "server.unreachable": {
20262
+ category: "servers",
20263
+ action: "reported unreachable",
20264
+ label: "Server unreachable",
20265
+ tone: "danger",
20266
+ description: "Openship could not open an SSH connection to this server."
20267
+ },
20268
+ "server.reachable": {
20269
+ category: "servers",
20270
+ action: "reported reachable",
20271
+ label: "Server reachable again",
20272
+ tone: "success"
20273
+ },
20274
+ "server:write": {
20275
+ category: "servers",
20276
+ action: "changed the server",
20277
+ label: "Server changed"
20278
+ },
20279
+ "server:admin": {
20280
+ category: "servers",
20281
+ action: "ran an admin action on the server",
20282
+ label: "Server admin action",
20283
+ tone: "warning",
20284
+ description: "A destructive server endpoint was invoked, such as delete or component install."
20285
+ },
20286
+ "terminal:write": {
20287
+ category: "servers",
20288
+ action: "opened a terminal on",
20289
+ label: "Terminal session opened",
20290
+ tone: "warning",
20291
+ description: "An interactive shell session was issued against a server."
20292
+ },
20293
+ "mail_server:write": {
20294
+ category: "servers",
20295
+ action: "changed the mail server",
20296
+ label: "Mail server changed",
20297
+ description: "A mail server endpoint was invoked \u2014 setup, domain, DNS acknowledgement."
20298
+ },
20299
+ "mail_server:admin": {
20300
+ category: "servers",
20301
+ action: "ran an admin action on the mail server",
20302
+ label: "Mail server admin action",
20303
+ tone: "warning"
20304
+ },
20305
+ /* ---------------- Members & access ---------------- */
20306
+ "organization.created": {
20307
+ category: "members",
20308
+ action: "created the organization",
20309
+ label: "Organization created",
20310
+ tone: "info"
20311
+ },
20312
+ "organization.deleted": {
20313
+ category: "members",
20314
+ action: "deleted the organization",
20315
+ label: "Organization deleted",
20316
+ tone: "danger"
20317
+ },
20318
+ "organization.deletion.blocked": {
20319
+ category: "members",
20320
+ action: "tried to delete the organization",
20321
+ label: "Organization deletion blocked",
20322
+ tone: "warning",
20323
+ description: "Deletion was refused \u2014 active resources or billing still attached."
20324
+ },
20325
+ "member.added": {
20326
+ category: "members",
20327
+ action: "added",
20328
+ label: "Member added",
20329
+ tone: "info"
20330
+ },
20331
+ "member.removed": {
20332
+ category: "members",
20333
+ action: "removed",
20334
+ label: "Member removed",
20335
+ tone: "danger"
20336
+ },
20337
+ "member.role_changed": {
20338
+ category: "members",
20339
+ action: "changed the role of",
20340
+ label: "Member role changed",
20341
+ tone: "warning"
20342
+ },
20343
+ "member.joined": {
20344
+ category: "members",
20345
+ action: "joined",
20346
+ label: "Member joined",
20347
+ tone: "success",
20348
+ description: "An invitee accepted and now has access."
20349
+ },
20350
+ "member.invited": {
20351
+ category: "members",
20352
+ action: "invited",
20353
+ label: "Member invited",
20354
+ tone: "info"
20355
+ },
20356
+ "member.removal.grant_cleanup_failed": {
20357
+ category: "members",
20358
+ action: "removed, with leftover permissions,",
20359
+ label: "Removed member's permissions not cleaned up",
20360
+ tone: "warning",
20361
+ description: "The member is gone but their permission grants remained \u2014 review by hand."
20362
+ },
20363
+ "member.removal.subscription_cleanup_failed": {
20364
+ category: "members",
20365
+ action: "removed, with leftover billing,",
20366
+ label: "Removed member's billing not cleaned up",
20367
+ tone: "warning",
20368
+ description: "The member is gone but a linked subscription remained \u2014 review billing."
20369
+ },
20370
+ "invitation.created": {
20371
+ category: "members",
20372
+ action: "invited",
20373
+ label: "Invitation sent",
20374
+ tone: "info"
20375
+ },
20376
+ "invitation.sent": {
20377
+ category: "members",
20378
+ action: "invited, with pending permissions,",
20379
+ label: "Invitation sent with pending permissions",
20380
+ tone: "info",
20381
+ description: "Grants were queued and will apply the moment the invitee joins."
20382
+ },
20383
+ "invitation.accepted": {
20384
+ category: "members",
20385
+ action: "accepted the invitation of",
20386
+ label: "Invitation accepted",
20387
+ tone: "success"
20388
+ },
20389
+ "invitation.rejected": {
20390
+ category: "members",
20391
+ action: "declined the invitation of",
20392
+ label: "Invitation declined",
20393
+ tone: "warning"
20394
+ },
20395
+ "invitation.cancelled": {
20396
+ category: "members",
20397
+ action: "cancelled the invitation for",
20398
+ label: "Invitation cancelled",
20399
+ tone: "warning"
20400
+ },
20401
+ "team.created": {
20402
+ category: "members",
20403
+ action: "created the team",
20404
+ label: "Team created",
20405
+ tone: "info"
20406
+ },
20407
+ "grant.granted": {
20408
+ category: "members",
20409
+ action: "granted permissions to",
20410
+ label: "Permission granted",
20411
+ tone: "info"
20412
+ },
20413
+ "grant.revoked": {
20414
+ category: "members",
20415
+ action: "revoked permissions from",
20416
+ label: "Permission revoked",
20417
+ tone: "danger"
20418
+ },
20419
+ "grant.replaced": {
20420
+ category: "members",
20421
+ action: "replaced the permissions of",
20422
+ label: "Permission replaced",
20423
+ tone: "warning",
20424
+ description: "An existing grant was overwritten with a different scope."
20425
+ },
20426
+ "grant.materialized": {
20427
+ category: "members",
20428
+ action: "received their pending permissions,",
20429
+ label: "Pending permission applied",
20430
+ description: "A grant attached to an invitation was applied once the invitee joined."
20431
+ },
20432
+ "permissions:write": {
20433
+ category: "members",
20434
+ action: "changed permissions for",
20435
+ label: "Permissions changed",
20436
+ tone: "warning"
20437
+ },
20438
+ "permissions:admin": {
20439
+ category: "members",
20440
+ action: "ran an admin action on permissions for",
20441
+ label: "Permissions admin action",
20442
+ tone: "warning"
20443
+ },
20444
+ /* ---------------- Security ---------------- */
20445
+ "admin.bootstrapped": {
20446
+ category: "security",
20447
+ action: "bootstrapped the first admin account",
20448
+ label: "First admin account created",
20449
+ tone: "warning",
20450
+ description: "The instance's initial owner was created \u2014 this can only happen once."
20451
+ },
20452
+ "admin.password_reset": {
20453
+ category: "security",
20454
+ action: "reset an admin password",
20455
+ label: "Admin password reset",
20456
+ tone: "danger"
20457
+ },
20458
+ "auth-mode-changed": {
20459
+ category: "security",
20460
+ action: "changed the sign-in mode",
20461
+ label: "Sign-in mode changed",
20462
+ tone: "danger",
20463
+ description: "The instance switched between single-user and full authentication."
20464
+ },
20465
+ "instance.data.exported": {
20466
+ category: "security",
20467
+ action: "exported all instance data",
20468
+ label: "Instance data exported",
20469
+ tone: "warning",
20470
+ description: "A full database dump left this instance."
20471
+ },
20472
+ "instance.data.imported": {
20473
+ category: "security",
20474
+ action: "imported instance data",
20475
+ label: "Instance data imported",
20476
+ tone: "warning",
20477
+ description: "A database dump from another instance was loaded in."
20478
+ },
20479
+ // Written by the audit module itself. "disabled" is recorded before the switch
20480
+ // flips, so turning recording off always leaves this one row behind.
20481
+ "audit.disabled": {
20482
+ category: "security",
20483
+ action: "turned off activity recording",
20484
+ label: "Activity recording turned off",
20485
+ tone: "danger",
20486
+ description: "No further actions were recorded until recording was turned back on."
20487
+ },
20488
+ "audit.enabled": {
20489
+ category: "security",
20490
+ action: "turned on activity recording",
20491
+ label: "Activity recording turned on",
20492
+ tone: "success"
20493
+ },
20494
+ "audit.retention_changed": {
20495
+ category: "security",
20496
+ action: "changed how long activity is kept",
20497
+ label: "Activity retention changed",
20498
+ tone: "warning"
20499
+ },
20500
+ "audit:write": {
20501
+ category: "security",
20502
+ action: "changed activity recording",
20503
+ label: "Activity settings changed",
20504
+ tone: "warning"
20505
+ },
20506
+ /* ---------------- Billing ---------------- */
20507
+ "billing.hard_cap_tripped": {
20508
+ category: "billing",
20509
+ action: "hit the spending cap for",
20510
+ label: "Spending cap reached",
20511
+ tone: "danger",
20512
+ description: "Cloud resources may have been paused \u2014 review billing."
20513
+ },
20514
+ "billing.credit_exhausted": {
20515
+ category: "billing",
20516
+ action: "ran out of credits for",
20517
+ label: "Credits exhausted",
20518
+ tone: "warning",
20519
+ description: "Metered usage is paused until a top-up or the monthly reset."
20520
+ },
20521
+ "billing.credit_restored": {
20522
+ category: "billing",
20523
+ action: "restored credits for",
20524
+ label: "Credits restored",
20525
+ tone: "success"
20526
+ },
20527
+ "billing.anniversary_reset": {
20528
+ category: "billing",
20529
+ action: "reset the monthly credits of",
20530
+ label: "Monthly credits reset"
20531
+ },
20532
+ "quota.threshold_fired": {
20533
+ category: "billing",
20534
+ action: "crossed a usage threshold on",
20535
+ label: "Usage threshold crossed",
20536
+ tone: "warning"
20537
+ },
20538
+ "billing:write": {
20539
+ category: "billing",
20540
+ action: "changed billing for",
20541
+ label: "Billing action",
20542
+ description: "A billing endpoint was invoked \u2014 subscribe, top up, or open the portal."
20543
+ },
20544
+ "billing:admin": {
20545
+ category: "billing",
20546
+ action: "ran an admin action on billing for",
20547
+ label: "Billing admin action",
20548
+ tone: "warning",
20549
+ description: "A destructive billing endpoint was invoked, such as cancelling a subscription."
20550
+ },
20551
+ /* ---------------- System ---------------- */
20552
+ "settings.updated": {
20553
+ category: "system",
20554
+ action: "updated settings",
20555
+ label: "Settings updated"
20556
+ },
20557
+ "settings:write": {
20558
+ category: "system",
20559
+ action: "changed settings",
20560
+ label: "Settings changed"
20561
+ },
20562
+ "settings:admin": {
20563
+ category: "system",
20564
+ action: "ran an admin action on settings",
20565
+ label: "Settings admin action",
20566
+ tone: "warning",
20567
+ description: "A destructive settings endpoint was invoked, such as a wipe or migration."
20568
+ },
20569
+ "updates:write": {
20570
+ category: "system",
20571
+ action: "applied an update",
20572
+ label: "Update applied",
20573
+ description: "An Openship component was updated or an update scan was triggered."
20574
+ },
20575
+ "cloud.disconnect": {
20576
+ category: "system",
20577
+ action: "disconnected from Openship Cloud",
20578
+ label: "Cloud disconnected",
20579
+ tone: "warning"
20580
+ },
20581
+ "cloud:write": {
20582
+ category: "system",
20583
+ action: "ran a cloud action",
20584
+ label: "Cloud action",
20585
+ description: "A cloud bridge endpoint was invoked \u2014 token, preflight, or edge proxy."
20586
+ },
20587
+ "cloud:admin": {
20588
+ category: "system",
20589
+ action: "ran a cloud admin action",
20590
+ label: "Cloud admin action",
20591
+ tone: "warning"
20592
+ },
20593
+ "github.install": {
20594
+ category: "system",
20595
+ action: "installed the GitHub app on",
20596
+ label: "GitHub app installed",
20597
+ tone: "info"
20598
+ },
20599
+ "github.disconnect": {
20600
+ category: "system",
20601
+ action: "disconnected GitHub from",
20602
+ label: "GitHub disconnected",
20603
+ tone: "warning"
20604
+ },
20605
+ "github.repo.create": {
20606
+ category: "system",
20607
+ action: "created the repository",
20608
+ label: "Repository created",
20609
+ tone: "info"
20610
+ },
20611
+ "github.repo.delete": {
20612
+ category: "system",
20613
+ action: "deleted the repository",
20614
+ label: "Repository deleted",
20615
+ tone: "danger"
20616
+ },
20617
+ "github.webhook.register": {
20618
+ category: "system",
20619
+ action: "enabled deploy-on-push for",
20620
+ label: "Deploy-on-push enabled",
20621
+ tone: "info"
20622
+ },
20623
+ "github.webhook.delete": {
20624
+ category: "system",
20625
+ action: "disabled deploy-on-push for",
20626
+ label: "Deploy-on-push disabled",
20627
+ tone: "warning"
20628
+ },
20629
+ "github.instance_token.set": {
20630
+ category: "system",
20631
+ action: "set the instance GitHub token",
20632
+ label: "Instance GitHub token set",
20633
+ tone: "warning",
20634
+ description: "A GitHub token shared by every project on this instance was stored."
20635
+ },
20636
+ "github:write": {
20637
+ category: "system",
20638
+ action: "changed a GitHub connection for",
20639
+ label: "GitHub action"
20640
+ },
20641
+ "github:admin": {
20642
+ category: "system",
20643
+ action: "ran a GitHub admin action on",
20644
+ label: "GitHub admin action",
20645
+ tone: "warning"
20646
+ },
20647
+ "notification_channel.created": {
20648
+ category: "system",
20649
+ action: "added the notification channel",
20650
+ label: "Notification channel added",
20651
+ tone: "info"
20652
+ },
20653
+ "notification_channel.updated": {
20654
+ category: "system",
20655
+ action: "updated the notification channel",
20656
+ label: "Notification channel updated"
20657
+ },
20658
+ "notification_channel.deleted": {
20659
+ category: "system",
20660
+ action: "removed the notification channel",
20661
+ label: "Notification channel removed",
20662
+ tone: "warning"
20663
+ },
20664
+ "notification_subscription.updated": {
20665
+ category: "system",
20666
+ action: "changed what is sent to",
20667
+ label: "Notification subscription changed"
20668
+ },
20669
+ "notification_subscription.deleted": {
20670
+ category: "system",
20671
+ action: "stopped notifications to",
20672
+ label: "Notification subscription removed",
20673
+ tone: "warning"
20674
+ },
20675
+ "notification_default.updated": {
20676
+ category: "system",
20677
+ action: "changed the notification defaults of",
20678
+ label: "Notification defaults changed"
20679
+ },
20680
+ "notifications:write": {
20681
+ category: "system",
20682
+ action: "changed notifications",
20683
+ label: "Notifications changed"
20684
+ },
20685
+ "notifications:admin": {
20686
+ category: "system",
20687
+ action: "ran a notifications admin action",
20688
+ label: "Notifications admin action",
20689
+ tone: "warning"
20690
+ },
20691
+ "backup_run.succeeded": {
20692
+ category: "system",
20693
+ action: "backed up",
20694
+ label: "Backup succeeded",
20695
+ tone: "success"
20696
+ },
20697
+ "backup_run.failed": {
20698
+ category: "system",
20699
+ action: "failed to back up",
20700
+ label: "Backup failed",
20701
+ tone: "danger"
20702
+ },
20703
+ "backup.webhook.fired": {
20704
+ category: "system",
20705
+ action: "triggered a backup of",
20706
+ label: "Backup triggered by webhook"
20707
+ },
20708
+ "backup.webhook.disabled": {
20709
+ category: "system",
20710
+ action: "disabled the backup webhook for",
20711
+ label: "Backup webhook disabled",
20712
+ tone: "warning",
20713
+ description: "The webhook failed too many times and was switched off."
20714
+ },
20715
+ "backup_destination:write": {
20716
+ category: "system",
20717
+ action: "changed the backup destination",
20718
+ label: "Backup destination changed"
20719
+ },
20720
+ "backup_destination:admin": {
20721
+ category: "system",
20722
+ action: "ran an admin action on the backup destination",
20723
+ label: "Backup destination admin action",
20724
+ tone: "warning"
20725
+ },
20726
+ "backup_destination:backup_policy:write": {
20727
+ category: "system",
20728
+ action: "changed the backup schedule of",
20729
+ label: "Backup schedule changed"
20730
+ },
20731
+ "backup_destination:backup_run:write": {
20732
+ category: "system",
20733
+ action: "ran a backup of",
20734
+ label: "Backup run"
20735
+ },
20736
+ "backup_destination:backup_restore:write": {
20737
+ category: "system",
20738
+ action: "restored from a backup of",
20739
+ label: "Restore from backup",
20740
+ tone: "warning"
20741
+ }
20742
+ };
20743
+ var CATEGORY_IDS = new Set(AUDIT_CATEGORIES.map((c) => c.id));
20744
+ var EVENT_TYPES_BY_CATEGORY = (() => {
20745
+ const map2 = {};
20746
+ for (const id of CATEGORY_IDS) map2[id] = [];
20747
+ for (const [eventType, def] of Object.entries(AUDIT_EVENTS)) {
20748
+ map2[def.category]?.push(eventType);
20749
+ }
20750
+ return map2;
20751
+ })();
20752
+
19493
20753
  export {
19494
20754
  LANGUAGES,
19495
20755
  STACKS,
@@ -19503,6 +20763,7 @@ export {
19503
20763
  shellSplitWords,
19504
20764
  commandToArgv,
19505
20765
  buildEdgeImageRef,
20766
+ buildMailImageRef,
19506
20767
  SYSTEM,
19507
20768
  resolveRedirectStatus,
19508
20769
  isValidEmail,
@@ -19523,6 +20784,8 @@ export {
19523
20784
  compareSemver,
19524
20785
  resolveCliUpdatePlan,
19525
20786
  cliInstallCommand,
19526
- PROXY_GZIP_TYPES,
19527
- sanitizeProxySettings
20787
+ PROXY_DIRECTIVES,
20788
+ sanitizeProxySettings,
20789
+ resolveProxyDirectives,
20790
+ parseProxyValue
19528
20791
  };