@automagik/omni 2.260910.8 → 2.260910.9

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.
@@ -37101,6 +37101,12 @@ function resolveTemplatePath(path, context2) {
37101
37101
  const specialValue = resolveSpecialValue(trimmed, root, rest, context2);
37102
37102
  if (specialValue !== undefined)
37103
37103
  return specialValue;
37104
+ if (trimmed === "payload_json")
37105
+ return JSON.stringify(context2.payload);
37106
+ if (trimmed === "event_json") {
37107
+ const { id = null, type = null, timestamp = null, metadata = null } = context2.event ?? {};
37108
+ return JSON.stringify({ id, type, timestamp, metadata, payload: context2.payload });
37109
+ }
37104
37110
  if (root === "payload")
37105
37111
  return rest ? getNestedValue(context2.payload, rest) : context2.payload;
37106
37112
  if (root === "env")
@@ -251638,7 +251644,7 @@ var init_sentry_scrub = __esm(() => {
251638
251644
  var require_package7 = __commonJS((exports, module) => {
251639
251645
  module.exports = {
251640
251646
  name: "@omni/api",
251641
- version: "2.260910.8",
251647
+ version: "2.260910.9",
251642
251648
  private: true,
251643
251649
  type: "module",
251644
251650
  exports: {
@@ -313265,6 +313271,7 @@ var init_scopes = __esm(() => {
313265
313271
  "GET /events/schemas": "events:read",
313266
313272
  "GET /events/schemas/:eventType": "events:read",
313267
313273
  "POST /events/schemas": "events:write",
313274
+ "POST /events/schemas/:eventType/validate": "events:read",
313268
313275
  "GET /events/consumers/:name": "events:read",
313269
313276
  "POST /events/consumers": "events:write",
313270
313277
  "DELETE /events/consumers/:name": "events:write",
@@ -314279,6 +314286,7 @@ var init_route_ownership = __esm(() => {
314279
314286
  "POST /api/v2/events/consumers/:name/ack",
314280
314287
  "POST /api/v2/events/consumers/:name/pull",
314281
314288
  "POST /api/v2/events/schemas",
314289
+ "POST /api/v2/events/schemas/:eventType/validate",
314282
314290
  "POST /api/v2/events/search",
314283
314291
  "POST /api/v2/events/trigger",
314284
314292
  "POST /api/v2/instances",
@@ -371217,6 +371225,11 @@ class EventSchemaService {
371217
371225
  const verdict = validateEventPayload(row.schema, payload);
371218
371226
  return { registered: true, valid: verdict.valid, errors: verdict.errors };
371219
371227
  }
371228
+ async validatePayload(eventType, payload) {
371229
+ const row = await this.getByTypeOrThrow(eventType);
371230
+ const verdict = validateEventPayload(row.schema, payload);
371231
+ return { eventType: row.eventType, version: row.version, enabled: row.enabled, ...verdict };
371232
+ }
371220
371233
  async lookupForGate(eventType) {
371221
371234
  const cached = this.gateCache.get(eventType);
371222
371235
  if (cached && cached.expiresAt > Date.now()) {
@@ -376026,6 +376039,7 @@ class WebhookService {
376026
376039
  if (this.eventBus) {
376027
376040
  const result = await this.eventBus.publishGeneric(eventType, payload, {
376028
376041
  correlationId: metadata?.correlationId,
376042
+ causationId: metadata?.causationId,
376029
376043
  instanceId: metadata?.instanceId,
376030
376044
  source: "manual-trigger"
376031
376045
  });
@@ -376395,14 +376409,38 @@ function handleDatabaseError(c, error3) {
376395
376409
  }
376396
376410
  return null;
376397
376411
  }
376398
- function handleUnknownError(c, error3) {
376399
- const message2 = error3 instanceof Error ? error3.message : "An unexpected error occurred";
376412
+ function describeDbError(error3) {
376413
+ const driver2 = unwrapDbError(error3);
376414
+ const rawCode = driver2 instanceof Error ? driver2.code : undefined;
376415
+ const driverCode = typeof rawCode === "string" ? rawCode : undefined;
376416
+ const isDriverError = driver2 instanceof Error && (driver2.name === "PostgresError" || driverCode !== undefined && PG_CONNECTION_CODES.has(driverCode));
376417
+ if (!(error3 instanceof DrizzleQueryError) && !isDriverError)
376418
+ return null;
376419
+ const connection2 = driverCode !== undefined && (PG_CONNECTION_CODES.has(driverCode) || driverCode.startsWith("08"));
376420
+ return {
376421
+ code: connection2 ? ERROR_CODES.DB_CONNECTION_FAILED : ERROR_CODES.DB_QUERY_FAILED,
376422
+ query: error3 instanceof DrizzleQueryError ? error3.query : undefined,
376423
+ driverCode,
376424
+ driverMessage: driver2 instanceof Error ? driver2.message : String(driver2)
376425
+ };
376426
+ }
376427
+ function safeErrorMessage(error3, fallback = "Unknown error") {
376428
+ const db2 = describeDbError(error3);
376429
+ if (db2)
376430
+ return db2.code === ERROR_CODES.DB_CONNECTION_FAILED ? "Database unavailable" : "Database query failed";
376431
+ return error3 instanceof Error ? error3.message : fallback;
376432
+ }
376433
+ function handleGenericDbError(c, info2) {
376400
376434
  return c.json({
376401
376435
  error: {
376402
- code: "INTERNAL_ERROR",
376403
- message: message2
376436
+ code: info2.code,
376437
+ message: info2.code === ERROR_CODES.DB_CONNECTION_FAILED ? "Database unavailable" : "Database query failed",
376438
+ retryable: true
376404
376439
  }
376405
- }, 500);
376440
+ }, ERROR_STATUS_MAP[info2.code]);
376441
+ }
376442
+ function handleUnknownError(c) {
376443
+ return c.json({ error: { code: "INTERNAL_ERROR", message: "Internal server error" } }, 500);
376406
376444
  }
376407
376445
  function routeError(c, error3) {
376408
376446
  if (error3 instanceof ZodError) {
@@ -376434,7 +376472,10 @@ function routeError(c, error3) {
376434
376472
  if (dbResult)
376435
376473
  return dbResult;
376436
376474
  }
376437
- return handleUnknownError(c, error3);
376475
+ const dbInfo = describeDbError(error3);
376476
+ if (dbInfo)
376477
+ return handleGenericDbError(c, dbInfo);
376478
+ return handleUnknownError(c);
376438
376479
  }
376439
376480
  function isCodeClientError(code) {
376440
376481
  if (PG_CLIENT_ERROR_CODES.has(code))
@@ -376463,7 +376504,7 @@ function isClientError(error3) {
376463
376504
  }
376464
376505
  return false;
376465
376506
  }
376466
- var log114, SENSITIVE_KEYS2, ERROR_STATUS_MAP, CHANNEL_ERROR_MAP, PG_CLIENT_ERROR_CODES, errorHandler2 = (error3, c) => {
376507
+ var log114, SENSITIVE_KEYS2, ERROR_STATUS_MAP, CHANNEL_ERROR_MAP, PG_CONNECTION_CODES, PG_CLIENT_ERROR_CODES, errorHandler2 = (error3, c) => {
376467
376508
  const requestId = c.get("requestId") ?? "unknown";
376468
376509
  if (isClientError(error3)) {
376469
376510
  log114.debug("Client error", {
@@ -376471,9 +376512,12 @@ var log114, SENSITIVE_KEYS2, ERROR_STATUS_MAP, CHANNEL_ERROR_MAP, PG_CLIENT_ERRO
376471
376512
  error: error3 instanceof Error ? error3.message : String(error3)
376472
376513
  });
376473
376514
  } else {
376515
+ const dbInfo = describeDbError(error3);
376474
376516
  log114.error("Server error", {
376475
376517
  requestId,
376476
- error: error3 instanceof Error ? error3.message : String(error3),
376518
+ error: dbInfo ? `${dbInfo.code}: ${dbInfo.driverMessage}` : error3 instanceof Error ? error3.message : String(error3),
376519
+ dbCode: dbInfo?.driverCode,
376520
+ query: dbInfo?.query,
376477
376521
  stack: error3 instanceof Error ? error3.stack : undefined
376478
376522
  });
376479
376523
  withScope2((scope) => {
@@ -376489,7 +376533,13 @@ var log114, SENSITIVE_KEYS2, ERROR_STATUS_MAP, CHANNEL_ERROR_MAP, PG_CLIENT_ERRO
376489
376533
  scope.setExtra("error.context", error3.context);
376490
376534
  }
376491
376535
  }
376492
- captureException(error3);
376536
+ if (dbInfo) {
376537
+ scope.setTag("error.code", dbInfo.code);
376538
+ scope.setExtra("db.query", dbInfo.query);
376539
+ captureException(unwrapDbError(error3));
376540
+ } else {
376541
+ captureException(error3);
376542
+ }
376493
376543
  });
376494
376544
  }
376495
376545
  return routeError(c, error3);
@@ -376498,6 +376548,7 @@ var init_error3 = __esm(() => {
376498
376548
  init_src();
376499
376549
  init_src5();
376500
376550
  init_esm6();
376551
+ init_drizzle_orm();
376501
376552
  init_http_exception();
376502
376553
  init_zod();
376503
376554
  log114 = createLogger("api:error");
@@ -376575,6 +376626,17 @@ var init_error3 = __esm(() => {
376575
376626
  SLACK_DM_REJECTED: { status: 403, message: "Slack DM was rejected by the recipient." },
376576
376627
  SLACK_UNKNOWN_ERROR: { status: 502, message: "An unexpected Slack error occurred." }
376577
376628
  };
376629
+ PG_CONNECTION_CODES = new Set([
376630
+ "CONNECT_TIMEOUT",
376631
+ "CONNECTION_CLOSED",
376632
+ "CONNECTION_DESTROYED",
376633
+ "CONNECTION_ENDED",
376634
+ "ECONNREFUSED",
376635
+ "ECONNRESET",
376636
+ "ETIMEDOUT",
376637
+ "ENOTFOUND",
376638
+ "EPIPE"
376639
+ ]);
376578
376640
  PG_CLIENT_ERROR_CODES = new Set(["23505", "23503"]);
376579
376641
  });
376580
376642
 
@@ -376819,7 +376881,7 @@ var import__package2, healthLog, VERSION5, startTime2, healthRoutes, getHealth =
376819
376881
  dbCheck = {
376820
376882
  status: "error",
376821
376883
  latency: Date.now() - dbStart,
376822
- error: error3 instanceof Error ? error3.message : "Unknown error"
376884
+ error: safeErrorMessage(error3)
376823
376885
  };
376824
376886
  }
376825
376887
  let natsCheck;
@@ -376851,6 +376913,7 @@ var init_health2 = __esm(() => {
376851
376913
  init_src5();
376852
376914
  init_drizzle_orm();
376853
376915
  init_dist2();
376916
+ init_error3();
376854
376917
  import__package2 = __toESM(require_package7(), 1);
376855
376918
  healthLog = createLogger("health");
376856
376919
  VERSION5 = import__package2.default.version;
@@ -380031,6 +380094,8 @@ var init_event_ops2 = __esm(() => {
380031
380094
  function registerEventSchemaSchemas(registry4) {
380032
380095
  registry4.register("EventSchema", EventSchemaSchema);
380033
380096
  registry4.register("RegisterEventSchemaRequest", RegisterEventSchemaSchema);
380097
+ registry4.register("ValidateEventPayloadRequest", ValidateEventPayloadSchema);
380098
+ registry4.register("EventPayloadValidation", EventPayloadValidationSchema);
380034
380099
  registry4.registerPath({
380035
380100
  method: "get",
380036
380101
  path: "/events/schemas",
@@ -380089,8 +380154,30 @@ function registerEventSchemaSchemas(registry4) {
380089
380154
  }
380090
380155
  }
380091
380156
  });
380157
+ registry4.registerPath({
380158
+ method: "post",
380159
+ path: "/events/schemas/{eventType}/validate",
380160
+ operationId: "validateEventPayload",
380161
+ tags: ["Events"],
380162
+ summary: "Validate a payload against a registered event schema (dry run)",
380163
+ description: "Check a payload against the registered schema with the same validator and error strings as the " + "webhook ingress and emit_event gates, without publishing an event or writing anything (no dead letter). " + "Returns 200 whether the payload is valid or not; read the `valid` flag and `errors`.",
380164
+ request: {
380165
+ params: exports_external.object({ eventType: exports_external.string().openapi({ description: "Event type (e.g. custom.github.push)" }) }),
380166
+ body: { content: { "application/json": { schema: ValidateEventPayloadSchema } } }
380167
+ },
380168
+ responses: {
380169
+ 200: {
380170
+ description: "Validation verdict",
380171
+ content: { "application/json": { schema: exports_external.object({ data: EventPayloadValidationSchema }) } }
380172
+ },
380173
+ 404: {
380174
+ description: "No schema registered for this type",
380175
+ content: { "application/json": { schema: ErrorSchema } }
380176
+ }
380177
+ }
380178
+ });
380092
380179
  }
380093
- var EVENT_TYPE_PATTERN, EventSchemaSchema, RegisterEventSchemaSchema;
380180
+ var EVENT_TYPE_PATTERN, EventSchemaSchema, RegisterEventSchemaSchema, ValidateEventPayloadSchema, EventPayloadValidationSchema;
380094
380181
  var init_event_schemas2 = __esm(() => {
380095
380182
  init_zod_openapi();
380096
380183
  init_common4();
@@ -380111,6 +380198,16 @@ var init_event_schemas2 = __esm(() => {
380111
380198
  description: exports_external.string().max(1000).optional().openapi({ description: "Description" }),
380112
380199
  enabled: exports_external.boolean().optional().openapi({ description: "Whether the validation gate is active (default true)" })
380113
380200
  });
380201
+ ValidateEventPayloadSchema = exports_external.object({
380202
+ payload: exports_external.unknown().openapi({ description: "The event payload to validate (any JSON value)" })
380203
+ }).refine((body) => ("payload" in body), { message: "payload is required", path: ["payload"] });
380204
+ EventPayloadValidationSchema = exports_external.object({
380205
+ eventType: exports_external.string().openapi({ description: "Event type the payload was checked against" }),
380206
+ version: exports_external.number().int().openapi({ description: "Schema revision used" }),
380207
+ enabled: exports_external.boolean().openapi({ description: "Whether the gate is active for this type (a disabled schema is still checked)" }),
380208
+ valid: exports_external.boolean().openapi({ description: "True when the payload satisfies the schema" }),
380209
+ errors: exports_external.array(exports_external.string()).openapi({ description: "Violations as `instancePath: message`, identical to the ingress gate; empty when valid" })
380210
+ });
380114
380211
  });
380115
380212
 
380116
380213
  // ../api/src/schemas/openapi/events.ts
@@ -383269,6 +383366,7 @@ var init_webhooks2 = __esm(() => {
383269
383366
  eventType: exports_external.string().min(1).openapi({ description: "Event type (must start with custom.)" }),
383270
383367
  payload: exports_external.record(exports_external.string(), exports_external.unknown()).openapi({ description: "Event payload" }),
383271
383368
  correlationId: exports_external.string().optional().openapi({ description: "Correlation ID" }),
383369
+ causationId: exports_external.string().uuid().optional().openapi({ description: "Parent event ID; stamps causationId so the emission is parented in the causality tree" }),
383272
383370
  instanceId: exports_external.string().uuid().optional().openapi({ description: "Instance ID for context" })
383273
383371
  });
383274
383372
  WebhookReceiveResponseSchema = exports_external.object({
@@ -386509,6 +386607,7 @@ var init_event_ops3 = __esm(() => {
386509
386607
  init_dist6();
386510
386608
  init_dist2();
386511
386609
  init_zod();
386610
+ init_error3();
386512
386611
  init_date_query();
386513
386612
  init_api_keys();
386514
386613
  eventOpsRoutes = new Hono2;
@@ -386546,6 +386645,8 @@ var init_event_ops3 = __esm(() => {
386546
386645
  const session3 = await services.eventOps.startReplay(options);
386547
386646
  return c.json({ data: session3 }, 202);
386548
386647
  } catch (err2) {
386648
+ if (describeDbError(err2))
386649
+ throw err2;
386549
386650
  return c.json({ error: String(err2) }, 400);
386550
386651
  }
386551
386652
  });
@@ -386608,6 +386709,13 @@ var init_event_schemas3 = __esm(() => {
386608
386709
  const data = await services.eventSchemas.register(input);
386609
386710
  return c.json({ data }, 201);
386610
386711
  });
386712
+ eventSchemasRoutes.post("/events/schemas/:eventType/validate", zValidator("json", ValidateEventPayloadSchema), async (c) => {
386713
+ const eventType = c.req.param("eventType");
386714
+ const { payload } = c.req.valid("json");
386715
+ const services = c.get("services");
386716
+ const data = await services.eventSchemas.validatePayload(eventType, payload);
386717
+ return c.json({ data });
386718
+ });
386611
386719
  });
386612
386720
 
386613
386721
  // ../api/src/routes/v2/events.ts
@@ -394987,6 +395095,7 @@ var init_scheduled_messages2 = __esm(() => {
394987
395095
  init_src();
394988
395096
  init_dist2();
394989
395097
  init_zod();
395098
+ init_error3();
394990
395099
  init_scheduled_messages();
394991
395100
  scheduledMessagesRoutes = new Hono2;
394992
395101
  scheduleSchema = exports_external.object({
@@ -395019,7 +395128,7 @@ var init_scheduled_messages2 = __esm(() => {
395019
395128
  throw error3;
395020
395129
  throw new OmniError({
395021
395130
  code: ERROR_CODES.UNKNOWN,
395022
- message: error3 instanceof Error ? error3.message : String(error3),
395131
+ message: safeErrorMessage(error3, String(error3)),
395023
395132
  recoverable: false,
395024
395133
  cause: error3 instanceof Error ? error3 : undefined
395025
395134
  });
@@ -395855,6 +395964,7 @@ var init_voice2 = __esm(() => {
395855
395964
  init_src2();
395856
395965
  init_dist2();
395857
395966
  init_zod();
395967
+ init_error3();
395858
395968
  voiceRoutes = new Hono2;
395859
395969
  joinSchema = exports_external.object({
395860
395970
  instanceId: exports_external.string().min(1),
@@ -395890,7 +396000,7 @@ var init_voice2 = __esm(() => {
395890
396000
  }
395891
396001
  }, 201);
395892
396002
  } catch (err2) {
395893
- return c.json({ error: { code: "VOICE_JOIN_FAILED", message: String(err2) } }, 500);
396003
+ return c.json({ error: { code: "VOICE_JOIN_FAILED", message: safeErrorMessage(err2) } }, 500);
395894
396004
  }
395895
396005
  });
395896
396006
  voiceRoutes.post("/leave", zValidator("json", leaveSchema), async (c) => {
@@ -395907,7 +396017,7 @@ var init_voice2 = __esm(() => {
395907
396017
  }
395908
396018
  return c.json({ success: true });
395909
396019
  } catch (err2) {
395910
- return c.json({ error: { code: "VOICE_LEAVE_FAILED", message: String(err2) } }, 500);
396020
+ return c.json({ error: { code: "VOICE_LEAVE_FAILED", message: safeErrorMessage(err2) } }, 500);
395911
396021
  }
395912
396022
  });
395913
396023
  voiceRoutes.get("/sessions", async (c) => {
@@ -396042,10 +396152,11 @@ var init_webhooks3 = __esm(() => {
396042
396152
  eventType: exports_external.string().min(1).refine((t) => t.startsWith("custom."), { message: 'Event type must start with "custom."' }).describe("Event type (must be custom.*)"),
396043
396153
  payload: exports_external.record(exports_external.string(), exports_external.unknown()).describe("Event payload"),
396044
396154
  correlationId: exports_external.string().optional().describe("Optional correlation ID"),
396155
+ causationId: exports_external.string().uuid().optional().describe("Optional parent event ID (causality tree, #1072)"),
396045
396156
  instanceId: exports_external.string().uuid().optional().describe("Optional instance ID for context")
396046
396157
  });
396047
396158
  webhooksRoutes.post("/events/trigger", zValidator("json", triggerEventSchema), async (c) => {
396048
- const { eventType, payload, correlationId, instanceId } = c.req.valid("json");
396159
+ const { eventType, payload, correlationId, causationId, instanceId } = c.req.valid("json");
396049
396160
  const services = c.get("services");
396050
396161
  const apiKey = c.get("apiKey");
396051
396162
  if (instanceId && apiKey && !ApiKeyService.instanceAllowed(apiKey.instanceIds, instanceId)) {
@@ -396053,6 +396164,7 @@ var init_webhooks3 = __esm(() => {
396053
396164
  }
396054
396165
  const result = await services.webhooks.trigger(eventType, payload, {
396055
396166
  correlationId,
396167
+ causationId,
396056
396168
  instanceId
396057
396169
  });
396058
396170
  return c.json(result, 201);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/omni",
3
- "version": "2.260910.8",
3
+ "version": "2.260910.9",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/automagik-dev/omni.git",