@rocicorp/zero 1.11.4 → 1.11.5

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 (192) hide show
  1. package/out/replicache/src/sync/request-id.js +2 -2
  2. package/out/replicache/src/sync/request-id.js.map +1 -1
  3. package/out/shared/src/bigint-json.d.ts.map +1 -1
  4. package/out/shared/src/bigint-json.js +1 -0
  5. package/out/shared/src/bigint-json.js.map +1 -1
  6. package/out/shared/src/headers.d.ts +12 -0
  7. package/out/shared/src/headers.d.ts.map +1 -0
  8. package/out/shared/src/headers.js +20 -0
  9. package/out/shared/src/headers.js.map +1 -0
  10. package/out/shared/src/random-uint64.d.ts.map +1 -1
  11. package/out/shared/src/random-uint64.js +2 -2
  12. package/out/shared/src/random-uint64.js.map +1 -1
  13. package/out/shared/src/random-values.d.ts +14 -1
  14. package/out/shared/src/random-values.d.ts.map +1 -1
  15. package/out/shared/src/random-values.js +24 -4
  16. package/out/shared/src/random-values.js.map +1 -1
  17. package/out/zero/package.js +1 -1
  18. package/out/zero/package.js.map +1 -1
  19. package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
  20. package/out/zero-cache/src/auth/auth.js +5 -0
  21. package/out/zero-cache/src/auth/auth.js.map +1 -1
  22. package/out/zero-cache/src/config/zero-config.d.ts +21 -0
  23. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  24. package/out/zero-cache/src/config/zero-config.js +47 -9
  25. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  26. package/out/zero-cache/src/custom-queries/transform-query.js +2 -2
  27. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  28. package/out/zero-cache/src/db/pg-to-lite.d.ts.map +1 -1
  29. package/out/zero-cache/src/db/pg-to-lite.js +3 -2
  30. package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
  31. package/out/zero-cache/src/db/pg-type-parser.d.ts +13 -0
  32. package/out/zero-cache/src/db/pg-type-parser.d.ts.map +1 -1
  33. package/out/zero-cache/src/db/pg-type-parser.js +55 -2
  34. package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
  35. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  36. package/out/zero-cache/src/server/change-streamer.js +5 -2
  37. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  38. package/out/zero-cache/src/server/inspector-delegate.d.ts +2 -25
  39. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  40. package/out/zero-cache/src/server/inspector-delegate.js +6 -29
  41. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  42. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  43. package/out/zero-cache/src/server/main.js +5 -0
  44. package/out/zero-cache/src/server/main.js.map +1 -1
  45. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  46. package/out/zero-cache/src/server/replicator.js +3 -2
  47. package/out/zero-cache/src/server/replicator.js.map +1 -1
  48. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  49. package/out/zero-cache/src/server/syncer.js +5 -4
  50. package/out/zero-cache/src/server/syncer.js.map +1 -1
  51. package/out/zero-cache/src/server/worker-dispatcher.d.ts.map +1 -1
  52. package/out/zero-cache/src/server/worker-dispatcher.js +2 -1
  53. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  54. package/out/zero-cache/src/services/admin-auth.d.ts +22 -0
  55. package/out/zero-cache/src/services/admin-auth.d.ts.map +1 -0
  56. package/out/zero-cache/src/services/admin-auth.js +42 -0
  57. package/out/zero-cache/src/services/admin-auth.js.map +1 -0
  58. package/out/zero-cache/src/services/auth-attempt-counter.d.ts +33 -0
  59. package/out/zero-cache/src/services/auth-attempt-counter.d.ts.map +1 -0
  60. package/out/zero-cache/src/services/auth-attempt-counter.js +61 -0
  61. package/out/zero-cache/src/services/auth-attempt-counter.js.map +1 -0
  62. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +1 -1
  63. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +7 -1
  64. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  65. package/out/zero-cache/src/services/change-source/pg/change-source.js +110 -13
  66. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  67. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +1 -1
  68. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +1 -1
  69. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +15 -8
  70. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  71. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +38 -5
  72. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  73. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  74. package/out/zero-cache/src/services/change-source/pg/schema/init.js +10 -1
  75. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  76. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +4 -0
  77. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  78. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +10 -3
  79. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  80. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +7 -1
  81. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  82. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +23 -2
  83. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  84. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +2 -2
  85. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  86. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +30 -9
  87. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  88. package/out/zero-cache/src/services/change-streamer/change-streamer.js +10 -3
  89. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  90. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts +1 -0
  91. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts.map +1 -1
  92. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +1 -1
  93. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  94. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  95. package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
  96. package/out/zero-cache/src/services/heapz.js +4 -5
  97. package/out/zero-cache/src/services/heapz.js.map +1 -1
  98. package/out/zero-cache/src/services/mutagen/pusher.js +1 -1
  99. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  100. package/out/zero-cache/src/services/plannerz.d.ts.map +1 -1
  101. package/out/zero-cache/src/services/plannerz.js +3 -7
  102. package/out/zero-cache/src/services/plannerz.js.map +1 -1
  103. package/out/zero-cache/src/services/profz.d.ts.map +1 -1
  104. package/out/zero-cache/src/services/profz.js +4 -13
  105. package/out/zero-cache/src/services/profz.js.map +1 -1
  106. package/out/zero-cache/src/services/replicator/change-processor.js +1 -2
  107. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  108. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  109. package/out/zero-cache/src/services/replicator/incremental-sync.js +3 -3
  110. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  111. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  112. package/out/zero-cache/src/services/statz.js +2 -7
  113. package/out/zero-cache/src/services/statz.js.map +1 -1
  114. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +16 -0
  115. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  116. package/out/zero-cache/src/services/view-syncer/client-handler.js +22 -1
  117. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  118. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +29 -4
  119. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -1
  120. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +40 -2
  121. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  122. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +10 -2
  123. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  124. package/out/zero-cache/src/services/view-syncer/cvr-store.js +40 -16
  125. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  126. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +8 -0
  127. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  128. package/out/zero-cache/src/services/view-syncer/cvr.js +11 -0
  129. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  130. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.d.ts +35 -0
  131. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.d.ts.map +1 -0
  132. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.js +107 -0
  133. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.js.map +1 -0
  134. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +2 -2
  135. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  136. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +11 -6
  137. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  138. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  139. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +2 -1
  140. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  141. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts +9 -0
  142. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts.map +1 -1
  143. package/out/zero-cache/src/services/view-syncer/schema/cvr.js +4 -1
  144. package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
  145. package/out/zero-cache/src/services/view-syncer/schema/init.d.ts.map +1 -1
  146. package/out/zero-cache/src/services/view-syncer/schema/init.js +3 -0
  147. package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
  148. package/out/zero-cache/src/services/view-syncer/snapshotter.js +1 -1
  149. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  150. package/out/zero-cache/src/services/view-syncer/view-syncer.js +96 -44
  151. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  152. package/out/zero-cache/src/types/client-group-log-id.d.ts +9 -0
  153. package/out/zero-cache/src/types/client-group-log-id.d.ts.map +1 -0
  154. package/out/zero-cache/src/types/client-group-log-id.js +16 -0
  155. package/out/zero-cache/src/types/client-group-log-id.js.map +1 -0
  156. package/out/zero-cache/src/types/lite.d.ts.map +1 -1
  157. package/out/zero-cache/src/types/lite.js +1 -0
  158. package/out/zero-cache/src/types/lite.js.map +1 -1
  159. package/out/zero-cache/src/types/pg.d.ts +13 -2
  160. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  161. package/out/zero-cache/src/types/pg.js +2 -2
  162. package/out/zero-cache/src/types/pg.js.map +1 -1
  163. package/out/zero-cache/src/workers/connection.d.ts +1 -0
  164. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  165. package/out/zero-cache/src/workers/connection.js +5 -1
  166. package/out/zero-cache/src/workers/connection.js.map +1 -1
  167. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  168. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +12 -3
  169. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  170. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  171. package/out/zero-cache/src/workers/syncer.js +15 -14
  172. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  173. package/out/zero-client/src/client/inspector/inspector.d.ts +4 -0
  174. package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
  175. package/out/zero-client/src/client/inspector/inspector.js +4 -0
  176. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  177. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +10 -2
  178. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
  179. package/out/zero-client/src/client/inspector/lazy-inspector.js +38 -31
  180. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  181. package/out/zero-client/src/client/inspector/query.d.ts +2 -2
  182. package/out/zero-client/src/client/inspector/query.d.ts.map +1 -1
  183. package/out/zero-client/src/client/inspector/query.js +4 -4
  184. package/out/zero-client/src/client/inspector/query.js.map +1 -1
  185. package/out/zero-client/src/client/version.js +1 -1
  186. package/out/zero-client/src/util/nanoid.js +2 -2
  187. package/out/zero-client/src/util/nanoid.js.map +1 -1
  188. package/out/zero-server/src/process-mutations.d.ts +10 -0
  189. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  190. package/out/zero-server/src/process-mutations.js +38 -5
  191. package/out/zero-server/src/process-mutations.js.map +1 -1
  192. package/package.json +1 -1
@@ -27,6 +27,7 @@ import "./initial-sync.js";
27
27
  import { streamBackfill } from "./backfill-stream.js";
28
28
  import { ReplicationSlotCleanupMonitor } from "./replication-slot-cleanup-monitor.js";
29
29
  import { registerReplicationSlotHealthMetrics } from "./replication-slot-health.js";
30
+ import { timingSafeEqual } from "node:crypto";
30
31
  import { nanoid } from "nanoid";
31
32
  import postgres from "postgres";
32
33
  import { PG_ADMIN_SHUTDOWN, PG_INSUFFICIENT_PRIVILEGE } from "@drdgvhbh/postgres-error-codes";
@@ -118,7 +119,8 @@ var PostgresChangeSource = class {
118
119
  */
119
120
  const isTransactionalMessage = (lsn, msg) => {
120
121
  if (msg.tag === "message" && msg.prefix === this.#lagReporter?.messagePrefix) {
121
- changes.pushStatus(this.#lagReporter.processLagReportMessage(msg, lsn));
122
+ const status = this.#lagReporter.processLagReportMessage(msg, lsn);
123
+ if (status) changes.pushStatus(status);
122
124
  return false;
123
125
  }
124
126
  const status = this.#lagReporter?.checkCurrentLSN(lsn);
@@ -325,6 +327,10 @@ var LagReporter = class LagReporter {
325
327
  description: "Number of replication lag reports retried because the expected report was not received before the next report interval.",
326
328
  unit: "{report}"
327
329
  });
330
+ #lagReportsIgnored = getOrCreateCounter("replication", "lag_reports_ignored", {
331
+ description: "Number of messages with the lag report prefix ignored because their content could not be parsed as a lag report.",
332
+ unit: "{message}"
333
+ });
328
334
  #pgVersion;
329
335
  #expectingLagReport = null;
330
336
  #lastAcceptedSendTimeMs = 0;
@@ -475,10 +481,22 @@ var LagReporter = class LagReporter {
475
481
  * XLogData header), rather than the `messageLsn` of the message itself,
476
482
  * which is not guaranteed to be comparable to other stream LSNs (e.g. on
477
483
  * Aurora). See {@link initiateLagReport}.
484
+ * @returns the status to send downstream, or `undefined` if the message is
485
+ * not a lag report. Any session that can call
486
+ * `pg_logical_emit_message()` can emit a message with the lag report
487
+ * prefix; one that cannot be parsed carries no report and is ignored,
488
+ * as a message of an unknown prefix would be, rather than failing the
489
+ * stream (which would replay it from the same position).
478
490
  */
479
491
  processLagReportMessage(msg, lsn) {
480
492
  assert(msg.prefix === this.messagePrefix, `unexpected message prefix: ${msg.prefix}`);
481
- const report = parseLogicalMessageContent(this.#lc, msg, lagReportSchema);
493
+ let report;
494
+ try {
495
+ report = parseLogicalMessageContent(this.#lc, msg, lagReportSchema);
496
+ } catch {
497
+ this.#lagReportsIgnored.add(1);
498
+ return;
499
+ }
482
500
  return this.#processLagReport(report, majorVersionToString(lsn));
483
501
  }
484
502
  #processLagReport(report, watermark) {
@@ -643,9 +661,50 @@ var ChangeMaker = class {
643
661
  default: throw new Error(`Unexpected message type ${stringify(msg)}`);
644
662
  }
645
663
  }
664
+ /**
665
+ * Any session that can call `pg_logical_emit_message()` can emit a message
666
+ * with the shard's ddl prefix. Only events that carry the shard's secret,
667
+ * which the upstream functions read from a table in the shard's schema
668
+ * (see `createEventFunctionStatements()`), are applied. Events emitted
669
+ * before the secret was installed (by functions that predate it) are
670
+ * accepted without one.
671
+ *
672
+ * @returns why the event cannot be verified, or `undefined` if it can.
673
+ */
674
+ #ddlEventOriginProblem(lsn, json, ddlSecret, ddlSecretLsn) {
675
+ const secret = field(json, "secret");
676
+ if (typeof secret === "string") {
677
+ if (equalSecrets(secret, ddlSecret)) return;
678
+ } else if ((secret === void 0 || secret === null) && ddlSecretLsn && lsn <= toBigInt(ddlSecretLsn)) return;
679
+ return `the event does not carry the secret of the ${upstreamSchema(this.#shard)} schema's event functions (secret ${typeof secret === "string" ? "mismatch" : "absent"}, installed at ${ddlSecretLsn ?? "unknown"})`;
680
+ }
646
681
  #lastReplicationEvent;
682
+ #ddlEventsIgnored = getOrCreateCounter("replication", "ddl_events_ignored", {
683
+ description: "Number of ddl messages ignored because they were not emitted by the shard's upstream functions (missing or wrong secret, or not valid JSON).",
684
+ unit: "{message}"
685
+ });
647
686
  #handleDdlMessage(lc, lsn, msg) {
648
- const event = parseLogicalMessageContent(lc, msg, replicationEventSchema);
687
+ const { ddlSecret, ddlSecretLsn } = this.#shardConfig;
688
+ assert(ddlSecret, "shard config has no ddl event secret");
689
+ const content = decodeLogicalMessage(msg);
690
+ let json;
691
+ let problem;
692
+ try {
693
+ json = JSON.parse(content);
694
+ } catch (e) {
695
+ problem = `not valid JSON: ${String(e)}`;
696
+ }
697
+ problem ??= this.#ddlEventOriginProblem(lsn, json, ddlSecret, ddlSecretLsn);
698
+ if (problem !== void 0) {
699
+ this.#ddlEventsIgnored.add(1);
700
+ lc.warn?.(`ignoring ${msg.prefix} message at ${fromBigInt(lsn)} (not emitted by the shard's upstream functions; replication continues): ${problem}`, describeUnverifiedMessage(json));
701
+ lc.debug?.(`ignored ${msg.prefix} message content`, { content: content.substring(0, 4096) });
702
+ return [];
703
+ }
704
+ const event = validateLogicalMessage(lc, msg, json, replicationEventSchema, () => stringify(field(json, "secret") === void 0 ? json : {
705
+ ...json,
706
+ secret: "<redacted>"
707
+ }));
649
708
  lc = lc.withContext("lsn", fromBigInt(lsn)).withContext("tag", event.event.tag).withContext("query", event.context.query);
650
709
  if (event.previousSchema) warnForSkippedIndexes(lc, event.previousSchema, this.#skippedIndexWarnings);
651
710
  if (event.schema) warnForSkippedIndexes(lc, event.schema, this.#skippedIndexWarnings);
@@ -999,8 +1058,7 @@ function summarizeSchemaForLog(schema) {
999
1058
  };
1000
1059
  }
1001
1060
  function summarizeReplicationEventForLog(event) {
1002
- const { schema, ...rest } = event;
1003
- const { previousSchema, ...eventWithoutSchemas } = rest;
1061
+ const { schema, previousSchema, secret: _, ...eventWithoutSchemas } = event;
1004
1062
  return {
1005
1063
  ...eventWithoutSchemas,
1006
1064
  ...schema !== void 0 && { schema: summarizeSchemaForLog(schema) },
@@ -1029,20 +1087,59 @@ var ShutdownSignal = class extends AbortError {
1029
1087
  super("shutdown signal received (e.g. another zero-cache taking over the replication stream)", { cause });
1030
1088
  }
1031
1089
  };
1090
+ function decodeLogicalMessage({ content }) {
1091
+ return content instanceof Buffer ? content.toString("utf-8") : new TextDecoder().decode(content);
1092
+ }
1032
1093
  function parseLogicalMessageContent(lc, msg, schema) {
1033
- const { content } = msg;
1034
- const str = content instanceof Buffer ? content.toString("utf-8") : new TextDecoder().decode(content);
1094
+ const str = decodeLogicalMessage(msg);
1095
+ let json;
1096
+ try {
1097
+ json = JSON.parse(str);
1098
+ } catch (e) {
1099
+ return failParse(lc, msg, e, str);
1100
+ }
1101
+ return validateLogicalMessage(lc, msg, json, schema, () => str);
1102
+ }
1103
+ function validateLogicalMessage(lc, msg, json, schema, contentForLog) {
1035
1104
  try {
1036
- const json = JSON.parse(str);
1037
1105
  return parse(json, schema, "passthrough");
1038
1106
  } catch (e) {
1039
- lc.error?.(`unable to parse logical message content: ${String(e)}`, { message: {
1040
- ...msg,
1041
- content: str
1042
- } });
1043
- throw e;
1107
+ return failParse(lc, msg, e, contentForLog());
1044
1108
  }
1045
1109
  }
1110
+ /**
1111
+ * Logs and rethrows a parse failure. Any session that can call
1112
+ * `pg_logical_emit_message()` can emit a message with a prefix that the
1113
+ * zero-cache parses, so the content is untrusted: it is logged at `warn`
1114
+ * (callers skip the message, so there is nothing for an operator to fix in
1115
+ * zero-cache) without the content, which goes to `debug`, bounded.
1116
+ */
1117
+ function failParse(lc, msg, e, content) {
1118
+ const { content: _, ...header } = msg;
1119
+ lc.warn?.(`unable to parse logical message content: ${String(e)}`, {
1120
+ message: header,
1121
+ contentLength: content.length
1122
+ });
1123
+ lc.debug?.(`unparseable logical message content`, { content: content.substring(0, 4096) });
1124
+ throw e;
1125
+ }
1126
+ /** A property of untrusted JSON, or `undefined` if there is no such property. */
1127
+ function field(json, name) {
1128
+ return typeof json === "object" && json !== null && name in json ? json[name] : void 0;
1129
+ }
1130
+ function describeUnverifiedMessage(json) {
1131
+ const str = (value) => typeof value === "string" ? value.substring(0, 200) : null;
1132
+ return {
1133
+ type: str(field(json, "type")),
1134
+ tag: str(field(field(json, "event"), "tag")),
1135
+ query: str(field(field(json, "context"), "query"))
1136
+ };
1137
+ }
1138
+ function equalSecrets(a, b) {
1139
+ const bufA = Buffer.from(a);
1140
+ const bufB = Buffer.from(b);
1141
+ return bufA.length === bufB.length && timingSafeEqual(bufA, bufB);
1142
+ }
1046
1143
  //#endregion
1047
1144
  export { Acker, LagReporter, PostgresChangeSource, isIndexStructurallyChanged, relationDifferent };
1048
1145