@rocicorp/zero 1.11.0-canary.31 → 1.11.0-canary.33

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 (109) hide show
  1. package/out/zero/package.js +2 -2
  2. package/out/zero/package.js.map +1 -1
  3. package/out/zero-cache/src/config/zero-config.d.ts +6 -0
  4. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  5. package/out/zero-cache/src/config/zero-config.js +14 -1
  6. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  7. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  8. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  9. package/out/zero-cache/src/server/change-streamer.js +1 -5
  10. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  11. package/out/zero-cache/src/server/slot-keeper.d.ts +26 -0
  12. package/out/zero-cache/src/server/slot-keeper.d.ts.map +1 -0
  13. package/out/zero-cache/src/server/slot-keeper.js +181 -0
  14. package/out/zero-cache/src/server/slot-keeper.js.map +1 -0
  15. package/out/zero-cache/src/server/worker-urls.d.ts +1 -0
  16. package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
  17. package/out/zero-cache/src/server/worker-urls.js +2 -1
  18. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  19. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +3 -13
  20. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -1
  21. package/out/zero-cache/src/services/change-source/common/replica-restore.js +4 -10
  22. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -1
  23. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts.map +1 -1
  24. package/out/zero-cache/src/services/change-source/pg/change-source-init.js +8 -8
  25. package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -1
  26. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  27. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +2 -1
  28. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  29. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +35 -1
  30. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  31. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +106 -22
  32. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  33. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +1 -1
  34. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  35. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +31 -9
  36. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  37. package/out/zero-cache/src/services/litestream/commands.d.ts +4 -11
  38. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  39. package/out/zero-cache/src/services/litestream/commands.js +4 -9
  40. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  41. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +3 -2
  42. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -1
  43. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +1 -1
  44. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  45. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  46. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +1 -1
  47. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  48. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  49. package/out/zero-cache/src/services/view-syncer/snapshotter.js +2 -2
  50. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  51. package/out/zero-cache/src/types/pg.js +1 -1
  52. package/out/zero-cache/src/types/processes.d.ts +3 -0
  53. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  54. package/out/zero-cache/src/types/processes.js.map +1 -1
  55. package/out/zero-cache/src/workers/connect-params.d.ts +6 -15
  56. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  57. package/out/zero-cache/src/workers/connect-params.js +14 -15
  58. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  59. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  60. package/out/zero-cache/src/workers/connection.js +1 -1
  61. package/out/zero-cache/src/workers/connection.js.map +1 -1
  62. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  63. package/out/zero-cache/src/workers/replicator.js +10 -1
  64. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  65. package/out/zero-client/src/client/version.js +1 -1
  66. package/out/zero-client/src/client/zero.js +2 -2
  67. package/out/zero-client/src/client/zero.js.map +1 -1
  68. package/out/zero-protocol/src/analyze-query-result.d.ts +1 -1
  69. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  70. package/out/zero-protocol/src/connect.d.ts +9 -12
  71. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  72. package/out/zero-protocol/src/connect.js +19 -16
  73. package/out/zero-protocol/src/connect.js.map +1 -1
  74. package/out/zero-protocol/src/poke.d.ts +3 -3
  75. package/out/zero-protocol/src/poke.js +1 -1
  76. package/out/zero-protocol/src/poke.js.map +1 -1
  77. package/out/zero-protocol/src/{feature-flag-enum.d.ts → protocol-flag-enum.d.ts} +1 -1
  78. package/out/zero-protocol/src/protocol-flag-enum.d.ts.map +1 -0
  79. package/out/zero-protocol/src/protocol-flag-enum.js +10 -0
  80. package/out/zero-protocol/src/protocol-flag-enum.js.map +1 -0
  81. package/out/zero-protocol/src/protocol-flag.d.ts +14 -0
  82. package/out/zero-protocol/src/protocol-flag.d.ts.map +1 -0
  83. package/out/zero-protocol/src/protocol-flag.js +8 -0
  84. package/out/zero-protocol/src/protocol-flag.js.map +1 -0
  85. package/out/zero-protocol/src/protocol-version.d.ts +3 -3
  86. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  87. package/out/zql/src/query/expression.d.ts +2 -2
  88. package/out/zql/src/query/expression.d.ts.map +1 -1
  89. package/out/zql/src/query/expression.js.map +1 -1
  90. package/out/zql/src/query/query.d.ts +5 -6
  91. package/out/zql/src/query/query.d.ts.map +1 -1
  92. package/out/zqlite/src/db.d.ts +8 -0
  93. package/out/zqlite/src/db.d.ts.map +1 -1
  94. package/out/zqlite/src/db.js +11 -0
  95. package/out/zqlite/src/db.js.map +1 -1
  96. package/package.json +2 -2
  97. package/out/shared/src/packed-boolean-map.d.ts +0 -7
  98. package/out/shared/src/packed-boolean-map.d.ts.map +0 -1
  99. package/out/shared/src/packed-boolean-map.js +0 -36
  100. package/out/shared/src/packed-boolean-map.js.map +0 -1
  101. package/out/zero-cache/src/services/litestream/wal-keeper.d.ts +0 -33
  102. package/out/zero-cache/src/services/litestream/wal-keeper.d.ts.map +0 -1
  103. package/out/zero-cache/src/services/litestream/wal-keeper.js +0 -49
  104. package/out/zero-cache/src/services/litestream/wal-keeper.js.map +0 -1
  105. package/out/zero-protocol/src/feature-flag-enum.d.ts.map +0 -1
  106. package/out/zero-protocol/src/feature-flag-enum.js +0 -10
  107. package/out/zero-protocol/src/feature-flag-enum.js.map +0 -1
  108. package/out/zero-protocol/src/feature-flag.d.ts +0 -5
  109. package/out/zero-protocol/src/feature-flag.d.ts.map +0 -1
@@ -1,6 +1,6 @@
1
1
  var package_default = {
2
2
  name: "@rocicorp/zero",
3
- version: "1.11.0-canary.31",
3
+ version: "1.11.0-canary.33",
4
4
  description: "Zero is a web framework for serverless web development.",
5
5
  homepage: "https://zero.rocicorp.dev",
6
6
  bugs: { "url": "https://bugs.rocicorp.dev" },
@@ -136,7 +136,7 @@ var package_default = {
136
136
  "@rocicorp/lock": "^1.0.4",
137
137
  "@rocicorp/logger": "^6.1.0",
138
138
  "@rocicorp/resolver": "^1.0.2",
139
- "@rocicorp/zero-sqlite3": "^1.1.4",
139
+ "@rocicorp/zero-sqlite3": "^1.1.5",
140
140
  "@standard-schema/spec": "^1.0.0",
141
141
  "@types/basic-auth": "^1.1.8",
142
142
  "@types/ws": "^8.5.12",
@@ -1 +1 @@
1
- {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.11.0-canary.31\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.5.5\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.218.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.76.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/resources\": \"^2.7.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-node\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.7.1\",\n \"@opentelemetry/semantic-conventions\": \"^1.41.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^6.1.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.1.4\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.3\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.65.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"analyze-query\": \"workspace:*\",\n \"ast-to-zql\": \"workspace:*\",\n \"expo-sqlite\": \">=15\",\n \"oxc-parser\": \"^0.129.0\",\n \"replicache\": \"workspace:*\",\n \"shared\": \"workspace:*\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typescript\": \"~7.0.2\",\n \"vite\": \"^8.0.13\",\n \"vitest\": \"^5.0.0\",\n \"zero-cache\": \"workspace:*\",\n \"zero-client\": \"workspace:*\",\n \"zero-pg\": \"workspace:*\",\n \"zero-react\": \"workspace:*\",\n \"zero-server\": \"workspace:*\",\n \"zero-solid\": \"workspace:*\",\n \"zqlite\": \"workspace:*\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@11.11.0\"\n}\n"],"mappings":""}
1
+ {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.11.0-canary.33\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.5.5\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.218.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.76.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/resources\": \"^2.7.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-node\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.7.1\",\n \"@opentelemetry/semantic-conventions\": \"^1.41.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^6.1.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.1.5\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.3\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.65.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"analyze-query\": \"workspace:*\",\n \"ast-to-zql\": \"workspace:*\",\n \"expo-sqlite\": \">=15\",\n \"oxc-parser\": \"^0.129.0\",\n \"replicache\": \"workspace:*\",\n \"shared\": \"workspace:*\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typescript\": \"~7.0.2\",\n \"vite\": \"^8.0.13\",\n \"vitest\": \"^5.0.0\",\n \"zero-cache\": \"workspace:*\",\n \"zero-client\": \"workspace:*\",\n \"zero-pg\": \"workspace:*\",\n \"zero-react\": \"workspace:*\",\n \"zero-server\": \"workspace:*\",\n \"zero-solid\": \"workspace:*\",\n \"zqlite\": \"workspace:*\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@11.11.0\"\n}\n"],"mappings":""}
@@ -784,6 +784,12 @@ export declare const zeroOptions: {
784
784
  };
785
785
  export type ZeroConfig = Config<typeof zeroOptions>;
786
786
  export declare function getZeroConfig(opts?: Omit<ParseOptions, 'envNamePrefix'>): ZeroConfig;
787
+ /**
788
+ * Parses only the log options, ignoring all other flags and environment
789
+ * variables. For lightweight workers that need to set up logging but do not
790
+ * need (or require) the rest of the zero config to be present or normalized.
791
+ */
792
+ export declare function getLogConfig(opts?: Omit<ParseOptions, 'envNamePrefix' | 'allowUnknown'>): Pick<ZeroConfig, 'log'>;
787
793
  /**
788
794
  * Same as {@link getZeroConfig}, with an additional check that the
789
795
  * config has already been normalized (i.e. by the top level server/runner).
@@ -1 +1 @@
1
- {"version":3,"file":"zero-config.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/config/zero-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"zero-config.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/config/zero-config.ts"],"names":[],"mappings":"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"}
@@ -1397,6 +1397,19 @@ function getZeroConfig(opts = {}) {
1397
1397
  return loadedConfig;
1398
1398
  }
1399
1399
  /**
1400
+ * Parses only the log options, ignoring all other flags and environment
1401
+ * variables. For lightweight workers that need to set up logging but do not
1402
+ * need (or require) the rest of the zero config to be present or normalized.
1403
+ */
1404
+ function getLogConfig(opts = {}) {
1405
+ return parseOptions({ log: logOptions }, {
1406
+ envNamePrefix: ZERO_ENV_VAR_PREFIX,
1407
+ emitDeprecationWarnings: false,
1408
+ allowUnknown: true,
1409
+ ...opts
1410
+ });
1411
+ }
1412
+ /**
1400
1413
  * Same as {@link getZeroConfig}, with an additional check that the
1401
1414
  * config has already been normalized (i.e. by the top level server/runner).
1402
1415
  */
@@ -1469,6 +1482,6 @@ function warnOnce(lc, msg) {
1469
1482
  }
1470
1483
  }
1471
1484
  //#endregion
1472
- export { ZERO_ENV_VAR_PREFIX, appOptions, getNormalizedZeroConfig, getOperatorAccess, getServerVersion, getZeroConfig, isAdminPasswordValid, shardOptions, zeroOptions };
1485
+ export { ZERO_ENV_VAR_PREFIX, appOptions, getLogConfig, getNormalizedZeroConfig, getOperatorAccess, getServerVersion, getZeroConfig, isAdminPasswordValid, shardOptions, zeroOptions };
1473
1486
 
1474
1487
  //# sourceMappingURL=zero-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zero-config.js","names":[],"sources":["../../../../../zero-cache/src/config/zero-config.ts"],"sourcesContent":["/**\n * These types represent the _compiled_ config whereas `define-config` types represent the _source_ config.\n */\n\nimport {timingSafeEqual} from 'node:crypto';\nimport type {LogContext} from '@rocicorp/logger';\nimport {logOptions} from '../../../otel/src/log-options.ts';\nimport {\n flagToEnv,\n parseOptions,\n type Config,\n type ParseOptions,\n} from '../../../shared/src/options.ts';\nimport * as v from '../../../shared/src/valita.ts';\n// @circular-dep-ignore - importing package.json for version info only\nimport packageJson from '../../../zero/package.json' with {type: 'json'};\nimport {runtimeDebugFlags} from '../../../zql/src/builder/debug-delegate.ts';\nimport {singleProcessMode} from '../types/processes.ts';\nimport {\n ALLOWED_APP_ID_CHARACTERS,\n INVALID_APP_ID_MESSAGE,\n} from '../types/shards.ts';\nimport {DEFAULT_PREFERRED_PREFIXES} from './network.ts';\nimport {\n assertNormalized,\n isDevelopmentMode,\n type NormalizedZeroConfig,\n} from './normalize.ts';\nexport type {LogConfig} from '../../../otel/src/log-options.ts';\n\nexport const ZERO_ENV_VAR_PREFIX = 'ZERO_';\n\nexport const appOptions = {\n id: {\n type: v\n .string()\n .optional(() => 'zero')\n .assert(id => ALLOWED_APP_ID_CHARACTERS.test(id), INVALID_APP_ID_MESSAGE),\n desc: [\n 'Unique identifier for the app.',\n '',\n 'Multiple zero-cache apps can run on a single upstream database, each of which',\n 'is isolated from the others, with its own permissions, sharding (future feature),',\n 'and change/cvr databases.',\n '',\n 'The metadata of an app is stored in an upstream schema with the same name,',\n 'e.g. \"zero\", and the metadata for each app shard, e.g. client and mutation',\n 'ids, is stored in the \"\\\\{app-id\\\\}_\\\\{#\\\\}\" schema. (Currently there is only a single',\n '\"0\" shard, but this will change with sharding).',\n '',\n 'The CVR and Change data are managed in schemas named \"\\\\{app-id\\\\}_\\\\{shard-num\\\\}/cvr\"',\n 'and \"\\\\{app-id\\\\}_\\\\{shard-num\\\\}/cdc\", respectively, allowing multiple apps and shards',\n 'to share the same database instance (e.g. a Postgres \"cluster\") for CVR and Change management.',\n '',\n 'Due to constraints on replication slot names, an App ID may only consist of',\n 'lower-case letters, numbers, and the underscore character.',\n '',\n 'Note that this option is used by both {bold zero-cache} and {bold zero-deploy-permissions}.',\n ],\n },\n\n publications: {\n type: v.array(v.string()).optional(() => []),\n desc: [\n `Postgres {bold PUBLICATION}s that define the tables and columns to`,\n `replicate. Publication names may not begin with an underscore,`,\n `as zero reserves that prefix for internal use.`,\n ``,\n `If unspecified, zero-cache will create and use an internal publication that`,\n `publishes all tables in the {bold public} schema, i.e.:`,\n ``,\n `CREATE PUBLICATION _\\\\{app-id\\\\}_public_0 FOR TABLES IN SCHEMA public;`,\n ``,\n `Note that changing the set of publications will result in resyncing the replica,`,\n `which may involve downtime (replication lag) while the new replica is initializing.`,\n `To change the set of publications without disrupting an existing app, a new app`,\n `should be created.`,\n ],\n },\n};\n\nexport const shardOptions = {\n id: {\n type: v\n .string()\n .assert(() => {\n throw new Error(\n `ZERO_SHARD_ID is no longer an option. Please use ZERO_APP_ID instead.`,\n // TODO: Link to release / migration notes?\n );\n })\n .optional(),\n hidden: true,\n },\n\n num: {\n type: v.number().optional(() => 0),\n desc: [\n `The shard number (from 0 to NUM_SHARDS) of the App. zero will eventually`,\n `support data sharding as a first-class primitive; until then, deploying`,\n `multiple shard-nums creates functionally identical shards. Until sharding is`,\n `actually meaningful, this flag is hidden but available for testing.`,\n ],\n hidden: true,\n },\n};\n\nconst replicaOptions = {\n file: {\n type: v.string().optional(() => 'zero.db'),\n desc: [\n `File path to the SQLite replica that zero-cache maintains.`,\n `This can be lost, but if it is, zero-cache will have to re-replicate next`,\n `time it starts up.`,\n ],\n },\n\n vacuumIntervalHours: {\n type: v.number().optional(),\n desc: [\n `Performs a VACUUM at server startup if the specified number of hours has elapsed`,\n `since the last VACUUM (or initial-sync). The VACUUM operation is heavyweight`,\n `and requires double the size of the db in disk space. If unspecified, VACUUM`,\n `operations are not performed.`,\n ],\n },\n};\n\nexport type ReplicaOptions = Config<typeof replicaOptions>;\n\nconst perUserMutationLimit = {\n max: {\n type: v.number().optional(),\n desc: [\n `The maximum mutations per user within the specified {bold windowMs}.`,\n `If unset, no rate limiting is enforced.`,\n ],\n },\n windowMs: {\n type: v.number().optional(() => 60_000),\n desc: [\n `The sliding window over which the {bold perUserMutationLimitMax} is enforced.`,\n ],\n },\n};\n\nexport type RateLimit = Config<typeof perUserMutationLimit>;\n\nconst authOptions = {\n jwk: {\n type: v.string().optional(),\n desc: [\n `A public key in JWK format used to verify JWTs. Only one of {bold jwk}, {bold jwksUrl} and {bold secret} may be set.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n jwksUrl: {\n type: v.string().optional(),\n desc: [\n `A URL that returns a JWK set used to verify JWTs. Only one of {bold jwk}, {bold jwksUrl} and {bold secret} may be set.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n secret: {\n type: v.string().optional(),\n desc: [\n `A symmetric key used to verify JWTs. Only one of {bold jwk}, {bold jwksUrl} and {bold secret} may be set.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n issuer: {\n type: v.string().optional(),\n desc: [\n `Expected issuer ({bold iss} claim) for JWT validation.`,\n `If set, tokens with a different or missing issuer will be rejected.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n audience: {\n type: v.string().optional(),\n desc: [\n `Expected audience ({bold aud} claim) for JWT validation.`,\n `If set, tokens with a different or missing audience will be rejected.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n revalidateIntervalSeconds: {\n type: v.number().optional(() => 300),\n desc: [\n `The interval in seconds between periodic /query auth revalidation for validated connections.`,\n `If unset, periodic auth revalidation is disabled.`,\n ],\n },\n retransformIntervalSeconds: {\n type: v.number().optional(() => 300),\n desc: [\n `The interval in seconds between periodic shared /query retransform work for a client group.`,\n `If unset, periodic shared retransform is disabled.`,\n ],\n },\n};\n\nconst makeDeprecationMessage = (flag: string) =>\n `Use {bold ${flagToEnv(ZERO_ENV_VAR_PREFIX, flag)}} (or {bold --${flag}}) instead.`;\n\nconst makeMutatorQueryOptions = (\n replacement: 'mutate' | 'query' | undefined,\n suffix: string,\n) => ({\n url: {\n type: v.array(v.string()).optional(), // optional until we remove CRUD mutations\n desc: [\n `The URL of the API server to which zero-cache will ${suffix}.`,\n ``,\n `{bold IMPORTANT:} URLs are matched using {bold URLPattern}, a standard Web API.`,\n ``,\n `{bold Pattern Syntax:}`,\n ` URLPattern uses a simple and intuitive syntax similar to Express routes.`,\n ` Wildcards and named parameters make it easy to match multiple URLs.`,\n ``,\n `{bold Basic Examples:}`,\n ` Exact URL match:`,\n ` \"https://api.example.com/mutate\"`,\n ` `,\n ` Any subdomain using wildcard:`,\n ` \"https://*.example.com/mutate\"`,\n ` `,\n ` Multiple subdomain levels:`,\n ` \"https://*.*.example.com/mutate\"`,\n ` `,\n ` Any path under a domain:`,\n ` \"https://api.example.com/*\"`,\n ` `,\n ` Named path parameters:`,\n ` \"https://api.example.com/:version/mutate\"`,\n ` ↳ Matches \"https://api.example.com/v1/mutate\", \"https://api.example.com/v2/mutate\", etc.`,\n ``,\n `{bold Advanced Patterns:}`,\n ` Optional path segments:`,\n ` \"https://api.example.com/:path?\"`,\n ` `,\n ` Regex in segments (for specific patterns):`,\n ` \"https://api.example.com/:version(v\\\\\\\\d+)/mutate\"`,\n ` ↳ Matches only \"v\" followed by digits`,\n ``,\n `{bold Multiple patterns:}`,\n ` [\"https://api1.example.com/mutate\", \"https://api2.example.com/mutate\"]`,\n ``,\n `{bold Note:} Query parameters and URL fragments (#) are automatically ignored during matching.`,\n ``,\n `For full URLPattern syntax, see: https://developer.mozilla.org/en-US/docs/Web/API/URLPattern`,\n ],\n ...(replacement\n ? {deprecated: [makeDeprecationMessage(`${replacement}-url`)]}\n : {}),\n },\n apiKey: {\n type: v.string().optional(),\n desc: [\n `An optional secret used to authorize zero-cache to call the API server handling writes.`,\n ],\n ...(replacement\n ? {deprecated: [makeDeprecationMessage(`${replacement}-api-key`)]}\n : {}),\n },\n forwardCookies: {\n type: v.boolean().optional(() => false),\n desc: [\n `If true, zero-cache will forward cookies from the request.`,\n `This is useful for passing authentication cookies to the API server.`,\n `If false, cookies are not forwarded.`,\n ],\n ...(replacement\n ? {deprecated: [makeDeprecationMessage(`${replacement}-forward-cookies`)]}\n : {}),\n },\n allowedClientHeaders: {\n type: v.array(v.string()).optional(),\n desc: [\n `A list of header names that clients are allowed to set via custom headers.`,\n `If specified, only headers in this list will be forwarded to the ${suffix === 'push mutations' ? 'push' : 'query'} URL.`,\n `Header names are case-insensitive.`,\n `If not specified, no client-provided headers are forwarded.`,\n `Example: ZERO_${replacement ? replacement.toUpperCase() : suffix === 'push mutations' ? 'MUTATE' : 'QUERY'}_ALLOWED_CLIENT_HEADERS=x-request-id,x-correlation-id`,\n ],\n ...(replacement\n ? {\n deprecated: [\n makeDeprecationMessage(`${replacement}-allowed-client-headers`),\n ],\n }\n : {}),\n },\n allowedRequestHeaders: {\n type: v.array(v.string()).optional(),\n desc: [\n `A list of header names to forward from the incoming HTTP request to the ${suffix === 'push mutations' ? 'push' : 'query'} URL.`,\n `Unlike {bold allowed-client-headers} (which forwards headers set by the client), these are taken`,\n `from the HTTP request that established the connection (e.g. headers injected by a proxy or load balancer).`,\n `If a listed header is present on the request, its value is forwarded upstream under the same header name.`,\n `Header names are case-insensitive.`,\n `If not specified, no request headers are forwarded.`,\n `Example: ZERO_${replacement ? replacement.toUpperCase() : suffix === 'push mutations' ? 'MUTATE' : 'QUERY'}_ALLOWED_REQUEST_HEADERS=x-forwarded-for,cf-ray`,\n ],\n ...(replacement\n ? {\n deprecated: [\n makeDeprecationMessage(`${replacement}-allowed-request-headers`),\n ],\n }\n : {}),\n },\n});\n\nconst mutateOptions = makeMutatorQueryOptions(undefined, 'push mutations');\nconst pushOptions = makeMutatorQueryOptions('mutate', 'push mutations');\nconst queryOptions = makeMutatorQueryOptions(undefined, 'send synced queries');\nconst getQueriesOptions = makeMutatorQueryOptions(\n 'query',\n 'send synced queries',\n);\n\nexport type AuthConfig = Config<typeof authOptions>;\n\n/** @deprecated used only by legacy JWT verification helpers */\nexport type LegacyJWTAuthConfig = Pick<\n AuthConfig,\n 'jwk' | 'jwksUrl' | 'secret' | 'issuer' | 'audience'\n>;\n\n// Note: --help will list flags in the order in which they are defined here,\n// so order the fields such that the important (e.g. required) ones are first.\n// (Exported for testing)\nexport const zeroOptions = {\n upstream: {\n db: {\n type: v.string(),\n desc: [\n `The \"upstream\" authoritative postgres database.`,\n `In the future we will support other types of upstream besides PG.`,\n ],\n },\n\n type: {\n type: v.literalUnion('pg', 'custom').optional(() => 'pg'),\n desc: [\n `The meaning of the {bold upstream-db} depends on the upstream type:`,\n `* {bold pg}: The connection database string, e.g. \"postgres://...\"`,\n `* {bold custom}: The base URI of the change source \"endpoint, e.g.`,\n ` \"https://my-change-source.dev/changes/v0/stream?apiKey=...\"`,\n ],\n hidden: true, // TODO: Unhide when ready to officially support.\n },\n\n maxConns: {\n type: v.number().optional(() => 20),\n desc: [\n `The maximum number of connections to open to the upstream database`,\n `for committing mutations. This is divided evenly amongst sync workers.`,\n `In addition to this number, zero-cache uses one connection for the`,\n `replication stream.`,\n ``,\n `Note that this number must allow for at least one connection per`,\n `sync worker, or zero-cache will fail to start. See {bold num-sync-workers}`,\n ],\n },\n\n maxConnsPerWorker: {\n type: v.number().optional(),\n hidden: true, // Passed from main thread to sync workers\n },\n\n pgReplicationSlotFailover: {\n type: v.boolean().optional(),\n desc: [\n `For upstream Postgres versions 17+, creates replication slots with the`,\n `{bold failover} parameter set to {bold true} to enable slot synchronization`,\n `and failover. Note that additional Postgres-level configuration is necessary`,\n `when enabling this option. For details, see:`,\n ``,\n `https://www.postgresql.org/docs/current/logicaldecoding-explanation.html#LOGICALDECODING-REPLICATION-SLOTS-SYNCHRONIZATION`,\n ``,\n `(Note that this option has no effect for Postgres versions before 17.)`,\n ],\n },\n\n pgReplicationSlotPerReplica: {\n type: v.boolean().optional(() => false),\n desc: [\n `Creates a dedicated replication slot for each replication-manager, rather than`,\n `having a new replication-manager take over the slot of the one it replaces.`,\n ``,\n `A new replication-manager restores its replica from the backup, creates its own slot`,\n `and starts replicating from the head of the change-db's change log while the previous`,\n `replication-manager continues to serve. Once it has caught up to that head, it takes`,\n `over the change log. The replica's backup and the change-db remain compatible with`,\n `the default (shared slot) mode, so disabling this option does not trigger a resync.`,\n ``,\n `This is a rollback-safe intermediate step towards an upcoming high-availability mode,`,\n `in which multiple replication-managers run concurrently with their own slots, each`,\n `maintaining a local change log instead of the global change log in the change-db.`,\n `Running with this option first validates the per-replica slot setup, and rolling back`,\n `from high-availability mode to this configuration re-initializes the change-db's change`,\n `log from the replica rather than requiring a resync.`,\n ``,\n `Requires litestream v5 backups. Each slot retains upstream WAL until it is consumed or`,\n `dropped. Slots of replication-managers that are no longer running are dropped`,\n `automatically.`,\n ],\n },\n\n pgHighAvailabilityReplication: {\n type: v.boolean().optional(),\n desc: [\n `Runs replication-managers in high-availability mode, allowing multiple tasks to`,\n `run concurrently, each using their own replication slot and maintaining a local`,\n `change-log in sqlite.`,\n ``,\n `In this configuration, the PG change-streamer db is not used or maintained. Consequently`,\n `after running servers in high-availability mode, rolling back to a legacy singleton-mode task`,\n `will trigger a resync in order to re-intialize the PG change-streamer db.`,\n // Note: This is a feature flag that automatically enables the necessary\n // implementation flags:\n // ZERO_UPSTREAM_PG_REPLICATION_SLOT_PER_REPLICA = true\n // ZERO_LITESTREAM_BACKUP_USING_V5 = true,\n // ZERO_CHANGE_STREAMER_SQLITE_CHANGE_LOG_MODE = serve\n // ZERO_CHANGE_STREAMER_SQLITE_CHANGE_LOG_READ_PERCENT = 100\n // ZERO_CHANGE_STREAMER_SQLITE_CHANGE_LOG_COLD_READ_PERCENT = 100\n // ZERO_CHANGE_STREAMER_PG_CHANGE_LOG_ENABLED = false\n ],\n hidden: true, // TODO: Expose / roll out.\n },\n\n pgResumeOrphanedSlotGracePeriodMs: {\n type: v.number().optional(() => 20_000),\n desc: [\n `The grace period to wait before taking over an inactive replication slot, \"resuming\"`,\n `the replica. With high availability replication, a new replica is generally \"forked\"`,\n `from a running, active replica. Resumption happens as a last resort when no there are no`,\n `active replicas, as it carries the risk of stealing the slot from a task that is attempting`,\n `to reconnect to its slot.`,\n ``,\n `In local development, where it is often expected for slots to be inactive, it is reasonable to set`,\n `this to value to 0.`,\n ],\n hidden: true,\n },\n\n pgReplicationEpoch: {\n type: v.number().optional(() => 0),\n desc: [\n `Replication managers sharing the same epoch attempt to converge on a single`,\n `generation (i.e. the result of an initial-sync); if multiple tasks are started`,\n `simultaneously, they coordinate with each other such that one performs the`,\n `initial-sync while the others wait for it.`,\n ``,\n `Incrementing the epoch is the way to reliably force a resync; a replication manager`,\n `on a new epoch will ignore any replicas on other epochs.`,\n ``,\n `Note that changing the {bold ZERO_LITESTREAM_BACKUP_URL} generally achieves a resync`,\n `as well, but with high available replication managers, changing only the backup url can`,\n `lead to confusion if an old replication manager is performing initial sync, causing the`,\n `new replication manager to wait for it. Incrementing the replication epoch is recommended`,\n `instead.`,\n ],\n hidden: true,\n },\n\n // Temporary rollout gate. This defaults off for the compatibility\n // deployment; enable it after all replication managers can consume\n // partial-index schema snapshots.\n pgPartialIndexTriggers: {\n type: v.boolean().optional(() => false),\n hidden: true,\n },\n\n pgStreamInboundTimeoutMs: {\n type: v.number().optional(),\n desc: [\n `The time (in milliseconds) without any inbound message from the upstream`,\n `wal sender after which the replication stream is considered unresponsive`,\n `and torn down to force a reconnect.`,\n ``,\n `Defaults to 2x the server's {bold wal_sender_timeout}. That suits idle`,\n `streams, but a busy wal sender can be legitimately silent for longer —`,\n `e.g. while decoding through WAL from unpublished tables, or assembling a`,\n `large transaction that is only sent at commit. If the server's`,\n `{bold wal_sender_timeout} is aggressive (some managed environments`,\n `default it as low as 5 seconds), the resulting teardown aborts and`,\n `replays the in-flight transaction, which can prevent replication from`,\n `ever catching up on a large backlog. Set this option to widen the`,\n `client-side threshold without changing the server setting.`,\n ``,\n `(This option has no effect when {bold wal_sender_timeout} is 0, which`,\n `disables inbound liveness detection entirely.)`,\n ],\n },\n },\n\n /** @deprecated */\n push: pushOptions,\n mutate: mutateOptions,\n /** @deprecated */\n getQueries: getQueriesOptions,\n query: queryOptions,\n\n enableCrudMutations: {\n type: v.boolean().optional(() => true),\n desc: [\n `Enables support for legacy CRUD mutations. When this is {bold false}, no connections`,\n `are made from view-syncers to the upstream db, and push messages with CRUD mutations`,\n `result in an InvalidPush response.`,\n ],\n },\n\n allowLegacyQueries: {\n type: v.boolean().optional(() => false),\n desc: [\n `Allows clients to send legacy query ASTs directly to zero-cache.`,\n `Keep this disabled when using custom queries so that zero-cache rejects`,\n `client-supplied ASTs without parsing them.`,\n ],\n },\n\n cvr: {\n db: {\n type: v.string().optional(),\n desc: [\n `The Postgres database used to store CVRs. CVRs (client view records) keep track`,\n `of the data synced to clients in order to determine the diff to send on reconnect.`,\n `If unspecified, the {bold upstream-db} will be used.`,\n ],\n },\n\n maxConns: {\n type: v.number().optional(() => 30),\n desc: [\n `The maximum number of connections to open to the CVR database.`,\n `This is divided evenly amongst sync workers.`,\n ``,\n `Note that this number must allow for at least one connection per`,\n `sync worker, or zero-cache will fail to start. See {bold num-sync-workers}`,\n ],\n },\n\n maxConnsPerWorker: {\n type: v.number().optional(),\n hidden: true, // Passed from main thread to sync workers\n },\n\n garbageCollectionInactivityThresholdHours: {\n type: v.number().optional(() => 24 * 7),\n desc: [\n `The duration after which an inactive CVR is eligible for garbage collection.`,\n `Purging a CVR forces the next connection from that client group to`,\n `re-sync from scratch, so this should comfortably exceed how long a`,\n `typical user goes between sessions.`,\n `Note that garbage collection is an incremental, periodic process which does not`,\n `necessarily purge all eligible CVRs immediately.`,\n ],\n },\n\n garbageCollectionInitialIntervalSeconds: {\n type: v.number().optional(() => 60),\n desc: [\n `The initial interval at which to check and garbage collect inactive CVRs.`,\n `This interval is increased exponentially (up to 16 minutes) when there is`,\n `nothing to purge.`,\n ],\n },\n\n garbageCollectionInitialBatchSize: {\n type: v.number().optional(() => 25),\n desc: [\n `The initial number of CVRs to purge per garbage collection interval.`,\n `This number is increased linearly if the rate of new CVRs exceeds the rate of`,\n `purged CVRs, in order to reach a steady state.`,\n ``,\n `Setting this to 0 effectively disables CVR garbage collection.`,\n ],\n },\n },\n\n queryHydrationStats: {\n type: v.boolean().optional(),\n desc: [\n `Track and log the number of rows considered by query hydrations which`,\n `take longer than {bold log-slow-hydrate-threshold} milliseconds.`,\n `This is useful for debugging and performance tuning.`,\n ],\n },\n\n sqliteCorruptionChecks: {\n type: v.boolean().optional(() => false),\n desc: [\n `Run SQLite quick_check and integrity_check when corruption is detected.`,\n `These checks scan the replica and can take a long time on large databases.`,\n ],\n hidden: true,\n },\n\n snapshotRowCacheSize: {\n type: v.number().optional(() => 50_000),\n desc: [\n `The maximum number of entries in the per-worker cache of replica rows`,\n `read while advancing IVM pipelines. Every client group on a sync worker`,\n `reads the new and previous value of each replicated row change; the`,\n `cache lets the client groups on a worker share those reads. A replicated`,\n `transaction of N rows produces up to 2N entries.`,\n ``,\n `Setting this to 0 disables the cache.`,\n ],\n hidden: true,\n },\n\n enableQueryPlanner: {\n type: v.boolean().optional(() => true),\n desc: [\n `Enable the query planner for optimizing ZQL queries.`,\n ``,\n `The query planner analyzes and optimizes query execution by determining`,\n `the most efficient join strategies.`,\n ``,\n `You can disable the planner if it is picking bad strategies.`,\n ],\n },\n\n enableCorrelatedPredicatePushdown: {\n type: v.boolean().optional(() => true),\n desc: [\n `Copy a query's equality conditions on a relationship's join columns`,\n `into the related subquery. This reduces the rows that are read when a`,\n `change is pushed through the query.`,\n ``,\n `This is a kill switch. It will be removed.`,\n ],\n hidden: true,\n },\n\n enablePlannerAwarePushdown: {\n type: v.boolean().optional(() => true),\n desc: [\n `Copy the conditions of correlated predicate pushdown before the query`,\n `planner runs instead of after, so that the planner can use them. This`,\n `can change the plans that the planner picks.`,\n ``,\n `Has no effect when correlated predicate pushdown is off.`,\n ],\n hidden: true,\n },\n\n enableQueryCovering: {\n type: v.boolean().optional(() => true),\n desc: [\n `Enable shadow-mode query covering detection during query hydration.`,\n ``,\n `When enabled, view-syncers compare newly hydrated queries against running`,\n `queries with the same root table and log aggregate coverage stats.`,\n ``,\n `You can disable this if covering detection adds too much CPU overhead.`,\n ],\n },\n\n deferIvmWrites: {\n type: v.boolean().optional(() => true),\n desc: [\n `Derive IVM advancements without writing to the replica snapshot.`,\n ``,\n `A view-syncer normally makes each change durable in the SQLite snapshot`,\n `it is reading from, because the next change has to read a base that`,\n `includes the previous ones. Those writes are always rolled back -- the`,\n `replicator is the only committer -- so they exist only to serve reads`,\n `for the rest of the advancement.`,\n ``,\n `When enabled (the default), the changes are held in memory and merged`,\n `into each leaf scan instead, leaving the snapshot read-only, within the`,\n `budget set by {bold deferIvmWritesHeapProportion}. Disable it to write`,\n `every advancement through to the snapshot. The two modes are required`,\n `to be indistinguishable to the pipelines above the source.`,\n ],\n hidden: true,\n },\n\n deferIvmWritesHeapProportion: {\n type: v\n .number()\n .assert(\n value => value > 0 && value <= 1,\n 'must be greater than 0 and at most 1',\n )\n .optional(() => 0.25),\n desc: [\n `With {bold deferIvmWrites}, the proportion of {bold --max-old-space-size}`,\n `that the client groups of one sync worker may hold in memory at once.`,\n `Each client group holds its own copy of the changes it is advancing`,\n `through. Before an advancement starts, the number of rows it will`,\n `change is reserved from this budget, at an assumed 1 KiB per row; an`,\n `advancement that does not fit is written`,\n `through to the replica snapshot instead, as when {bold deferIvmWrites}`,\n `is off. The bytes the rows are estimated to hold are also added up as`,\n `the client groups go, and a client group that takes the total past the`,\n `budget writes the rows it holds through to the replica snapshot, and`,\n `the rest of its changes after them.`,\n ],\n hidden: true,\n },\n\n yieldThresholdMs: {\n type: v.number().optional(() => 10),\n desc: [\n `The maximum amount of time in milliseconds that a sync worker will`,\n `spend in IVM (processing query hydration and advancement) before yielding`,\n `to the event loop. Lower values increase responsiveness and fairness at`,\n `the cost of reduced throughput.`,\n ],\n },\n\n viewSyncerHydrationBudgetMs: {\n type: v\n .number()\n .assert(\n value => Number.isSafeInteger(value) && value >= 0,\n 'must be a nonnegative integer',\n )\n .optional(() => 0),\n desc: [\n `The soft time budget in milliseconds for hydrating inactive queries`,\n `during a view-syncer hydration pass. Active and internal queries always`,\n `finish, and time spent in custom-query transform round trips is not`,\n `charged to the budget. An inactive query not reached before the budget`,\n `is spent is evicted: its CVR record and the remaining TTL that would`,\n `have kept it warm are both dropped. A value of 0 disables`,\n `hydration-budget eviction.`,\n ],\n },\n\n viewSyncerQueryHydrationTimeoutMs: {\n type: v\n .number()\n .assert(\n value => Number.isSafeInteger(value) && value >= 0,\n 'must be a nonnegative integer',\n )\n .optional(() => 0),\n desc: [\n `The maximum processing time in milliseconds that a view-syncer spends`,\n `hydrating a single client query. Time spent yielding to other work is`,\n `not counted. A query whose hydration exceeds this limit is aborted and`,\n `removed from the client's view, and affected clients receive an error`,\n `for the query. The query is then rejected without being run again for`,\n `a cooldown period, after which a retry is allowed. Internal queries are`,\n `never aborted. A value of 0 disables the limit.`,\n ],\n },\n\n change: {\n db: {\n type: v.string().optional(),\n desc: [\n `The Postgres database used to store recent replication log entries, in order`,\n `to sync multiple view-syncers without requiring multiple replication slots on`,\n `the upstream database. If unspecified, the {bold upstream-db} will be used.`,\n ],\n },\n\n /** @deprecated */\n maxConns: {\n type: v.number().optional(() => 5),\n deprecated: [\n `Connections to the change db are created dynamically for subscriber catchup. Ensure`,\n `that the database supports sufficient connections for at least 5 + numViewSyncers.`,\n ],\n hidden: true,\n },\n\n statementTimeoutMs: {\n type: v.number().optional(() => 30_000),\n desc: [\n `Fail change-log db operations that make no progress within the specified timeout. This`,\n `differs from a postgres {bold statement_timeout} in that it is implemented to handle a`,\n `pathological case in which Postgres does not return a response but otherwise believes the`,\n `connection to be idle (e.g. a half-open connection).`,\n ],\n hidden: true, // make visible if proven to be effective/necessary\n },\n\n logBatchSize: {\n type: v\n .number()\n .assert(\n n => Number.isInteger(n) && n >= 1,\n `change.logBatchSize must be an integer >= 1`,\n )\n .optional(() => 2000),\n desc: [\n `The maximum number of change-log rows written per multi-row INSERT to the change`,\n `database. Larger upstream transactions are persisted in batches of this size rather`,\n `than one INSERT per change, which is the dominant cost when replicating large`,\n `transactions (e.g. bulk backfills or migrations). Larger values increase throughput`,\n `at the cost of higher transient memory; the effective batch is internally capped to`,\n `stay within Postgres's bind-parameter limit. Set to {bold 1} to disable batching.`,\n ],\n hidden: true, // make visible if proven to be effective/necessary\n },\n },\n\n replica: replicaOptions,\n\n log: logOptions,\n\n app: appOptions,\n\n shard: shardOptions,\n\n auth: authOptions,\n\n port: {\n type: v.number().optional(() => 4848),\n desc: [`The port for sync connections.`],\n },\n\n keepaliveTimeoutMs: {\n type: v.number().optional(),\n desc: [\n `The timeout since the last /keepalive request after which the server will initiate`,\n `a graceful shutdown. This is a workaround for AWS Elastic Container Service, which`,\n `otherwise provides no signal that a target has been deregistered (and should thus begin`,\n `shutdown); the cessation of health checks at /keepalive is instead used as the signal to`,\n `drain. (ECS later sends a SIGTERM before killing the server but only allows a 30-second`,\n `timeout before sending SIGKILL).`,\n ``,\n `Other container runners explicitly send a SIGTERM followed by a configurable drain interval,`,\n `in which case /keepalive logic is not necessary.`,\n ``,\n `When running the server in ECS, this timeout should be set to some multiple of the health`,\n `check interval. If the option is unset, the keepalive timeout is disabled in non-ECS environments,`,\n `and defaults to 20 seconds when run in ECS (determined by the presence of the`,\n `{bold ECS_CONTAINER_METADATA_URI_V4} environment variable as per`,\n `https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-environment-variables.html).`,\n ],\n },\n\n changeStreamer: {\n uri: {\n type: v.string().optional(),\n desc: [\n `When set, connects to the {bold change-streamer} at the given URI.`,\n `In a multi-node setup, this should be specified in {bold view-syncer} options,`,\n `pointing to the {bold replication-manager} URI, which runs a {bold change-streamer}`,\n `on port 4849.`,\n ],\n },\n\n mode: {\n type: v.literalUnion('dedicated', 'discover').optional(() => 'dedicated'),\n desc: [\n `As an alternative to {bold ZERO_CHANGE_STREAMER_URI}, the {bold ZERO_CHANGE_STREAMER_MODE}`,\n `can be set to \"{bold discover}\" to instruct the {bold view-syncer} to connect to the `,\n `ip address registered by the {bold replication-manager} upon startup.`,\n ``,\n `This may not work in all networking configurations, e.g. certain private `,\n `networking or port forwarding configurations. Using the {bold ZERO_CHANGE_STREAMER_URI}`,\n `with an explicit routable hostname is recommended instead.`,\n ``,\n `Note: This option is ignored if the {bold ZERO_CHANGE_STREAMER_URI} is set.`,\n ],\n },\n\n port: {\n type: v.number().optional(),\n desc: [\n `The port on which the {bold change-streamer} runs. This is an internal`,\n `protocol between the {bold replication-manager} and {bold view-syncers}, which`,\n `runs in the same process tree in local development or a single-node configuration.`,\n ``,\n `If unspecified, defaults to {bold --port} + 1.`,\n ],\n },\n\n /** @deprecated */\n address: {\n type: v.string().optional(),\n deprecated: [\n `Set the {bold ZERO_CHANGE_STREAMER_URI} on view-syncers instead.`,\n ],\n hidden: true,\n },\n\n /** @deprecated */\n protocol: {\n type: v.literalUnion('ws', 'wss').optional(() => 'ws'),\n deprecated: [\n `Set the {bold ZERO_CHANGE_STREAMER_URI} on view-syncers instead.`,\n ],\n hidden: true,\n },\n\n discoveryInterfacePreferences: {\n type: v.array(v.string()).optional(() => [...DEFAULT_PREFERRED_PREFIXES]),\n desc: [\n `The name prefixes to prefer when introspecting the network interfaces to determine`,\n `the externally reachable IP address for change-streamer discovery. This defaults`,\n `to commonly used names for standard ethernet interfaces in order to prevent selecting`,\n `special interfaces such as those for VPNs.`,\n ],\n // More confusing than it's worth to advertise this. The default list should be\n // adjusted to make things work for all environments; it is controlled as a\n // hidden flag as an emergency to unblock people with outlier network configs.\n hidden: true,\n },\n\n startupDelayMs: {\n type: v.number().optional(() => 15000),\n desc: [\n `The delay to wait before the change-streamer takes over the replication stream`,\n `(i.e. the handoff during replication-manager updates), to allow loadbalancers to register`,\n `the task as healthy based on healthcheck parameters. Note that if a change stream request`,\n `is received during this interval, the delay will be canceled and the takeover will happen`,\n `immediately, since the incoming request indicates that the task is registered as a target.`,\n ],\n },\n\n sqliteChangeLogMode: {\n type: v\n .literalUnion('off', 'write', 'compare', 'serve')\n .optional(() => 'off'),\n desc: [\n `Controls the staged SQLite change-log rollout. Modes are cumulative:`,\n `{bold off}, {bold write}, {bold compare}, and {bold serve}.`,\n ],\n hidden: true,\n },\n\n pgChangeLogEnabled: {\n type: v.boolean().optional(() => true),\n desc: [\n `Whether the legacy Postgres change log remains authoritative for`,\n `stream initialization, persistence, catchup, and upstream ACKs.`,\n `Disabling it requires SQLite serve mode at 100 percent and a v5 backup.`,\n ],\n hidden: true,\n },\n\n sqliteChangeLogReadPercent: {\n type: v.number().optional(() => 0),\n desc: [\n `The stable percentage of eligible catchup subscriptions served from SQLite.`,\n ],\n hidden: true,\n },\n\n sqliteChangeLogColdReadPercent: {\n type: v.number().optional(() => 0),\n desc: [\n `The stable percentage of eligible catchup subscriptions served from a`,\n `SQLite change log that is younger than its retention window, i.e. one`,\n `seeded less than {bold --change-streamer-sqlite-change-log-retention-ms}`,\n `ago. Selection uses the same hash as`,\n `{bold --change-streamer-sqlite-change-log-read-percent}, so a task that`,\n `serves cold is always one that would serve warm.`,\n ],\n hidden: true,\n },\n\n sqliteChangeLogComparePercent: {\n type: v.number().optional(() => 1),\n desc: [\n `The stable percentage of committed transactions whose catchup output is`,\n `compared between the Postgres and SQLite change logs in {bold compare} mode.`,\n ],\n hidden: true,\n },\n\n sqliteChangeLogRetentionMs: {\n type: v.number().optional(() => 60_000),\n desc: [`The minimum time window retained in the SQLite change log.`],\n hidden: true,\n },\n\n sqliteChangeLogReadBatchRows: {\n type: v.number().optional(() => 1000),\n desc: [`The target number of rows in each SQLite catchup read batch.`],\n hidden: true,\n },\n\n sqliteChangeLogPurgeBatchRows: {\n type: v.number().optional(() => 1000),\n desc: [`The target number of rows in each SQLite purge batch.`],\n hidden: true,\n },\n\n sqliteChangeLogBarrierTimeoutMs: {\n type: v.number().optional(() => 300_000),\n desc: [\n `The maximum wait for the SQLite required-head barrier. This is a`,\n `backstop for a wedged replica on an idle shard, where waiting costs`,\n `nothing and would otherwise go unnoticed. A shard with traffic is`,\n `bounded well before this by the subscriber's backlog reaching its`,\n `high water mark, which is the point at which waiting starts holding`,\n `up replication.`,\n ],\n hidden: true,\n },\n\n backPressureLimitHeapProportion: {\n type: v.number().optional(() => 0.04),\n desc: [\n `The percentage of {bold --max-old-space-size} to use as a buffer for absorbing replication`,\n `stream spikes. When the estimated amount of queued data exceeds this threshold, back pressure`,\n `is applied to the replication stream, delaying downstream sync as a result.`,\n ``,\n `The threshold was determined empirically with load testing. Higher thresholds have resulted`,\n `in OOMs. Note also that the byte-counting logic in the queue is strictly an underestimate of`,\n `actual memory usage (but importantly, proportionally correct), so the queue is actually`,\n `using more than what this proportion suggests.`,\n ``,\n `This parameter is exported as an emergency knob to reduce the size of the buffer in the`,\n `event that the server OOMs from back pressure. Resist the urge to {italic increase} this`,\n `proportion, as it is mainly useful for absorbing periodic spikes and does not meaningfully`,\n `affect steady-state replication throughput; the latter is determined by other factors such`,\n `as object serialization and PG throughput`,\n ``,\n `In other words, the back pressure limit does not constrain replication throughput;`,\n `rather, it protects the system when the upstream throughput exceeds the downstream`,\n `throughput.`,\n ],\n },\n\n flowControlConsensusTimeoutProportion: {\n type: v.number().optional(() => 4.0),\n desc: [\n `During periodic flow control checks (every 64kb), the amount of time to wait after the majority`,\n `of subscribers have acked, proportional to that interval, after which replication will continue`,\n `even if some subscribers have yet to ack.`,\n ``,\n `This allows a bounded amount of time for backlogged subscribers to catch up on each flush`,\n `without forcing all subscribers to wait for the entire backlog to be processed. It is also`,\n `useful for mitigating the effect of unresponsive subscribers due to severed websocket`,\n `connections or pathological zombie situations (until liveness checks or laggard detection`,\n `disconnects them).`,\n ``,\n `For example, if the majority of subscribers ack a message in 2.5ms, a padding proportion of`,\n `1.0 instructs replication to continue after an additional 2.5ms; for a proportion of 2.0, an`,\n `additional 5.0ms, etc. The default value of 4.0 allows for a subscriber to be 5x slower than the`,\n `majority in the steady state, while similarly bounding the extent to which a temporarily lagging`,\n `subscriber (e.g. due to catchup) slows down the fleet.`,\n ``,\n `Note that subscribers that continually exceed the timeout will eventually be disconnected and`,\n `instructed to shutdown in order to protect the healthy subscribers. It is thus important that`,\n `the proportion account for expected variance in processing speed across subscribers.`,\n ``,\n `Set this to a negative number to disable early flow control releases. (Not recommended, but`,\n `available as an emergency measure.)`,\n ],\n },\n\n flowControlSlowSubscriberGracePeriodSeconds: {\n type: v.number().optional(() => 30),\n desc: [\n `The period of time after which a lagging subscriber is disconnected and instructed to`,\n `restart. A subscriber is considered lagging if it {italic continuously} (1) exceeds the`,\n `consensus timeout and (2) fails to exceed the change rate of healthy subscribers. These`,\n `conditions distinguish expected, temporary periods of slowness from pathological`,\n `scenarios, such as zombie tasks, in which the subscriber is unlikely to recover.`,\n ``,\n `In particular, the second condition excludes subscribers that are performing initial`,\n `catchup, as the rate of change for catchup must eventually exceed the rate of upstream`,\n `changes. Note, however, that catchup rate can be legitimately slow during (rare) expensive`,\n `operations such as index creation.`,\n ``,\n `Thus, this grace period caps the amount of time that a lagging subscriber degrades overall`,\n `throughput, but should be long enough to allow for legitimate intervals of slowness.`,\n ``,\n `Note that in the pathological case where a catchup operation exceeds this grace period,`,\n `the system will eventually recover after the next backup/restore cycle, as the expensive`,\n `operation (e.g. index creation) will have been applied to the restored replica and no longer`,\n `executed during catchup.`,\n ``,\n `Set this to 0 or a negative number to disable laggard detection. (Not recommended, but`,\n `available as an emergency measure.)`,\n ],\n },\n },\n\n taskID: {\n type: v.string().optional(),\n desc: [\n `Globally unique identifier for the zero-cache instance.`,\n ``,\n `Setting this to a platform specific task identifier can be useful for debugging.`,\n `If unspecified, zero-cache will attempt to extract the TaskARN if run from within`,\n `an AWS ECS container, and otherwise use a random string.`,\n ],\n },\n\n perUserMutationLimit,\n\n numSyncWorkers: {\n type: v.number().optional(),\n desc: [\n `The number of processes to use for view syncing.`,\n `Leave this unset to use the maximum available parallelism.`,\n `If set to 0, the server runs without sync workers, which is the`,\n `configuration for running the {bold replication-manager}.`,\n ],\n },\n\n autoReset: {\n type: v.boolean().optional(() => true),\n desc: [\n `Automatically wipe and resync the replica when replication is halted.`,\n `This situation can occur for configurations in which the upstream database`,\n `provider prohibits event trigger creation, preventing the zero-cache from`,\n `being able to correctly replicate schema changes. For such configurations,`,\n `an upstream schema change will instead result in halting replication with an`,\n `error indicating that the replica needs to be reset.`,\n ``,\n `When {bold auto-reset} is enabled, zero-cache will respond to such situations`,\n `by shutting down, and when restarted, resetting the replica and all synced `,\n `clients. This is a heavy-weight operation and can result in user-visible`,\n `slowness or downtime if compute resources are scarce.`,\n ],\n },\n\n replicationLag: {\n reportIntervalMs: {\n type: v.number().optional(() => 10000),\n desc: [\n `The approximate interval at which replication lag reports are written upstream and`,\n `reported via the {bold zero.replication.total_lag} opentelemetry metric. If`,\n `an expected report is not received before the next interval, Zero retries with`,\n `a new report and increments {bold zero.replication.lag_report_retries}.`,\n ``,\n `Note that the interval is approximate and scheduled with ~1 second jitter to allow`,\n `multiple replication-managers (in RMv2) to cooperatively share the same reports.`,\n ``,\n `When enabled, lag reports are used to gate readiness of servers coming online by waiting`,\n `for lag to fall below the {bold ZERO_REPLICATION_LAG_INITIAL_READINESS_THRESHOLD_MS}.`,\n `As such, the reporting interval determines the time for which a new server waits for`,\n `the next report to determine readiness.`,\n ``,\n `A negative or 0 value disables lag reporting and the associated readiness gating.`,\n ``,\n `This feature is only supported on the postgres upstream type.`,\n ],\n },\n\n initialReadinessThresholdMs: {\n type: v.number().optional(() => 1000),\n desc: [\n `The maximum replication lag in milliseconds that a server is allowed to have`,\n `before it advertises readiness (to serve traffic). This prevents the server`,\n `from serving stale data to clients when it is first started.`,\n ``,\n `Note that this is an initial readiness gate only. Once the server announces readiness,`,\n `it will continue to serve traffic even if the replication lag exceeds this threshold`,\n `thereafter.`,\n ``,\n `When lag reporting is disabled, readiness is not gated by replication lag.`,\n ],\n },\n\n maxReadinessDelayMs: {\n type: v.number().optional(() => 600_000), // 10 minutes\n desc: [\n `The maximum time in milliseconds that a server will wait for replication lag`,\n `to fall below the {bold ZERO_REPLICATION_LAG_INITIAL_READINESS_THRESHOLD_MS}`,\n `before it announces readiness. This prevents the server from waiting indefinitely`,\n `for lag to fall below the threshold, which can occur if the upstream database`,\n `is under heavy load or if there is a network partition.`,\n ],\n },\n },\n\n adminPassword: {\n type: v.string().optional(),\n desc: [\n `A password used to administer zero-cache server, for example to access the`,\n `/statz endpoint.`,\n '',\n 'A password is optional in development mode but {bold required in production} mode.',\n '',\n 'The admin password also grants access to everything that the',\n '{bold operator-password} does.',\n ],\n },\n\n operatorPassword: {\n type: v.string().optional(),\n desc: [\n `A password that grants access only to the diagnostic endpoints that cannot`,\n `expose application data, so that people who operate zero-cache can`,\n `diagnose it without being able to read the data it serves. These are:`,\n '',\n `* {bold /profz} and {bold /profrmz}: CPU profiles. Profiles served for the`,\n ` operator password have the source of every regular expression redacted,`,\n ` since those can contain LIKE patterns from client queries.`,\n `* {bold /statz}: counts and sizes.`,\n `* {bold /plannerz}: the replica's schema and planner statistics.`,\n '',\n `All other protected endpoints (the inspector and {bold /heapz}) still`,\n `require the {bold admin-password}.`,\n '',\n `For {bold /profrmz} in a multi-node deployment, the replication-manager`,\n `must be configured with the same operator password.`,\n '',\n `If it is the same as the {bold admin-password}, it grants admin access.`,\n ],\n },\n\n websocketCompression: {\n type: v.boolean().optional(() => false),\n desc: [\n 'Enable WebSocket per-message deflate compression.',\n '',\n 'Compression can reduce bandwidth usage for sync traffic but',\n 'increases CPU usage on both client and server. Disabled by default.',\n '',\n 'See: https://github.com/websockets/ws#websocket-compression',\n ],\n },\n\n websocketCompressionOptions: {\n type: v.string().optional(),\n desc: [\n 'JSON string containing WebSocket compression options.',\n '',\n 'Only used if websocketCompression is enabled.',\n '',\n 'Example: \\\\{\"zlibDeflateOptions\":\\\\{\"level\":3\\\\},\"threshold\":1024\\\\}',\n '',\n 'See https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback for available options.',\n ],\n },\n\n websocketMaxPayloadBytes: {\n type: v.number().optional(() => 10 * 1024 * 1024),\n desc: [\n 'Maximum size of incoming WebSocket messages in bytes.',\n '',\n 'Messages exceeding this limit are rejected before parsing.',\n 'Default: 10MB (10 * 1024 * 1024 = 10485760)',\n ],\n },\n\n litestream: {\n executable: {\n type: v.string().optional(),\n desc: [\n `Path to the {bold litestream} executable. This must be built from the`,\n `{bold rocicorp/litestream} fork. Support for the official binary at v0.5.x`,\n `is planned.`,\n ],\n },\n\n executableV5: {\n type: v.string().optional(),\n desc: [\n `The v0.5.x litestream executable which is used for restoring the backup`,\n `backup when {bold ZERO_LITESTREAM_RESTORE_USING_V5} is specified.`,\n `litestream v0.5.8+ can restore from both v0.3.x and v0.5.x backup formats,`,\n `affording forwards compatibility with a future zero-cache`,\n `version that will use litestream v0.5.x to backup the replica.`,\n ],\n },\n\n restoreUsingV5: {\n type: v.boolean().optional(() => true),\n desc: [\n `Restores the backup using the {bold ZERO_LITESTREAM_EXECUTABLE_V5} if specified.`,\n `This provides a recovery path if rolling back from {bold ZERO_LITESTREAM_BACKUP_USING_V5}`,\n `as v5 restores from both v3 and v5 backups (whichever is more recent).`,\n ],\n },\n\n backupUsingV5: {\n type: v.boolean().optional(() => true),\n desc: [\n `Backs up the replica using Litestream v0.5.x. This is required for (upcoming)`,\n `high-availability replication. Set to false to revert to Litestream v0.3.x backups.`,\n ``,\n `zero-cache requests an incremental backup every`,\n `{bold ZERO_LITESTREAM_INCREMENTAL_BACKUP_INTERVAL_SECONDS} and only acknowledges`,\n `changes upstream once a backup containing them has completed.`,\n ``,\n `Litestream v0.5.x allows only one writer per backup location, so each`,\n `replication-manager backs up to its own subfolder of the backup URL. Subfolders`,\n `left by previous replication-managers are not cleaned up automatically; that is`,\n `up to the operator. The simplest approach is a lifecycle expiration rule on the`,\n `object store (e.g. S3). Every file needed for a restore is at most about`,\n `{bold ZERO_LITESTREAM_SNAPSHOT_BACKUP_INTERVAL_HOURS} old, so an expiration of at`,\n `least twice that interval is safe.`,\n ``,\n `Requires {bold ZERO_LITESTREAM_RESTORE_USING_V5} (enabled by default).`,\n ],\n },\n\n forkBackup: {\n type: v.boolean().optional(() => true), // TODO: Vet and make non-optional\n hidden: true,\n desc: [\n `When a replication-manager restores from another replication-manager's`,\n `backup, also copies the restored backup files into its own (new) backup`,\n `subfolder, so that its first backup continues incrementally instead of`,\n `uploading a full snapshot of the replica.`,\n ``,\n `This only works with a {bold ZERO_LITESTREAM_EXECUTABLE_V5} that supports`,\n `{bold restore -fork-to-url}. The flag is ignored if {bold ZERO_LITESTREAM_BACKUP_USING_V5}`,\n `is disabled.`,\n ],\n },\n\n configPath: {\n type: v.string().optional(() => './src/services/litestream/config.yml'),\n desc: [\n `Path to the litestream yaml config file. zero-cache will run this with its`,\n `environment variables, which can be referenced in the file via $\\\\{ENV\\\\}`,\n `substitution, for example:`,\n `* {bold ZERO_REPLICA_FILE} for the db path`,\n `* {bold ZERO_LITESTREAM_BACKUP_LOCATION} for the db replica url`,\n `* {bold ZERO_LITESTREAM_LOG_LEVEL} for the log level`,\n `* {bold ZERO_LOG_FORMAT} for the log type`,\n ],\n },\n\n configPathV5: {\n type: v\n .string()\n .optional(() => './src/services/litestream/config-v5.yml'),\n desc: [\n `Path to the litestream v5 yaml config file. zero-cache will run this with its`,\n `environment variables, which can be referenced in the file via $\\\\{ENV\\\\}`,\n `substitution, for example:`,\n `* {bold ZERO_REPLICA_FILE} for the db path`,\n `* {bold ZERO_LITESTREAM_BACKUP_LOCATION} for the db replica url`,\n `* {bold ZERO_LITESTREAM_LOG_LEVEL} for the log level`,\n `* {bold ZERO_LOG_FORMAT} for the log type`,\n ],\n },\n\n logLevel: {\n type: v\n .literalUnion('debug', 'info', 'warn', 'error')\n .optional(() => 'warn'),\n },\n\n backupURL: {\n type: v.string().optional(),\n desc: [\n `The location of the litestream backup, usually an {bold s3://} URL.`,\n `This is only consulted by the {bold replication-manager}.`,\n `{bold view-syncers} receive this information from the {bold replication-manager}.`,\n ],\n },\n\n backupURLOverride: {\n type: v.string().optional(),\n desc: [`Overrides the backup URL when present.`],\n hidden: true, // internal use\n },\n\n endpoint: {\n type: v.string().optional(),\n desc: [\n `The S3-compatible endpoint URL to use for the litestream backup. Only required for non-AWS services.`,\n `The {bold replication-manager} and {bold view-syncers} must have the same endpoint.`,\n ],\n },\n\n region: {\n type: v.string().optional(),\n desc: [\n `The AWS region for the litestream backup bucket. Required for non-standard AWS partitions`,\n `(e.g. GovCloud {bold us-gov-west-1}) where Litestream cannot auto-detect the region.`,\n `The {bold replication-manager} and {bold view-syncers} must have the same region.`,\n ],\n },\n\n port: {\n type: v.number().optional(),\n desc: [\n `Port on which litestream exports metrics, used to determine the replication`,\n `watermark up to which it is safe to purge change log records.`,\n ``,\n `If unspecified, defaults to {bold --port} + 2.`,\n ],\n },\n\n checkpointThresholdMB: {\n type: v.number().optional(() => 40),\n desc: [\n `The size of the WAL file at which litestream performs background, best-effort (PASSIVE)`,\n `SQLite checkpoints to apply the writes in the WAL to the main database file. Checkpoints`,\n `result in new WAL (v3) or LTS (v5) files that are then backed up asynchronously.`,\n ``,\n `Note that these PASSIVE checkpoints are skipped if a write is in progress, so high writes rates`,\n `can precipitate runaway wal growth. Also see {bold ZERO_LITESTREAM_FORCE_CHECKPOINT_THRESHOLD_MB}`,\n ],\n },\n\n minCheckpointPageCount: {\n type: v.number().optional(),\n deprecated: [`Use {bold ZERO_CHECKPOINT_THRESHOLD_MB}`],\n hidden: true,\n },\n\n maxCheckpointPageCount: {\n type: v.number().optional(),\n desc: [\n `The WAL page count at which SQLite performs a RESTART checkpoint, which`,\n `blocks writers until complete. Defaults to {bold minCheckpointPageCount * 10}.`,\n `Set to {bold 0} to disable RESTART checkpoints entirely.`,\n ``,\n `This setting is only relevant when replicating with litestream v3, and is ignored`,\n `when replicating with litestream v5.`,\n ],\n },\n\n forceCheckpointThresholdMB: {\n type: v.number().optional(() => 256),\n desc: [\n `The size of the WAL file at which to pause writes and explicitly initiate a`,\n `local litestream sync. This is a safeguard for the situation in which litestream's`,\n `background checkpoints continually defer to incoming writes (i.e. high write load).`,\n ``,\n `If the WAL size reaches the forced checkpoint threshold, writes pause for an`,\n `an explicit litestream checkpoint, providing a flow-control mechanism to ensure timely`,\n `backups and prevent runaway wal growth.`,\n ``,\n `Note that these checkpoints {italic can} be skipped if litestream is performing a`,\n `snapshot at the time (though snapshots are disabled by default). For such configurations,`,\n `the {bold ZERO_LITESTREAM_MAX_WAL_SIZE_MB} provides an emergency break to prevent`,\n `exceeding available disk space.`,\n ``,\n `Set this to 0 to disable and instead rely on the litestream's default {bold truncate-page-n}`,\n `emergency break.`,\n ``,\n `This feature is only enabled with {bold ZERO_LITESTREAM_BACKUP_USING_V5}.`,\n ],\n },\n\n maxWalSizeMB: {\n type: v.number().optional(() => 10240),\n desc: [\n `A fail-safe that pauses writes once the un-checkpointed WAL reaches this size,`,\n `resuming when litestream manages to checkpoint it. This bounds WAL growth (and`,\n `ultimately disk usage) whenever litestream cannot checkpoint — e.g. while it holds`,\n `the checkpoint lock for an in-progress snapshot — and serves as an alternative to`,\n `litestream's {bold truncate-page-n} emergency checkpoint, which would otherwise block`,\n `writes for a second \"bounary\" snapshot.`,\n ``,\n `Size this generously relative to available disk; it should rarely be hit, as`,\n `{bold ZERO_LITESTREAM_FORCE_CHECKPOINT_THRESHOLD_MB} keeps the WAL far smaller in`,\n `normal operation. Set to {bold 0} to disable.`,\n ``,\n `This feature is only enabled with {bold ZERO_LITESTREAM_BACKUP_USING_V5}.`,\n ],\n },\n\n incrementalBackupIntervalMinutes: {\n type: v.number().optional(() => 15),\n desc: [\n `The interval between incremental v3 backups of the replica. Shorter intervals`,\n `reduce the amount of change history that needs to be replayed when catching`,\n `up a new view-syncer, at the expense of increasing the number of files needed`,\n `to download for the initial litestream restore.`,\n ``,\n `This option only applies to litestream v3 backups and will be deprecated/removed`,\n `once the zero-cache is transitioned to litestream v5. For configuring v5 backup`,\n `frequency, use {bold ZERO_LITESTREAM_INCREMENTAL_BACKUP_INTERVAL_SECONDS}.`,\n ],\n },\n\n snapshotBackupIntervalHours: {\n type: v.number().optional(() => 12),\n desc: [\n `The interval between snapshot backups of the replica. Applies to both`,\n `litestream v3 and v5 backups.`,\n ``,\n `For v3, each snapshot makes a full copy of the database to a new litestream`,\n `generation. This improves restore time at the expense of bandwidth.`,\n `Applications with a large database and low write rate can increase this`,\n `interval to reduce network usage for backups (litestream defaults to 24 hours).`,\n ``,\n `For v5, continuous compaction already keeps restore times low, so snapshots`,\n `serve a different purpose: they keep every file a restore needs within about`,\n `one interval of age, so that lifecycle policies can clean up old backups.`,\n `v5 snapshots are built by compacting the existing backup files rather than`,\n `reading the replica, so they do not block WAL checkpoints.`,\n ],\n },\n\n incrementalBackupIntervalSeconds: {\n type: v.number().optional(() => 15),\n desc: [\n `The interval between incremental v5 backups of the replica. With litestream v5`,\n `the upstream change source is not ACKed until the corresponding changes have been`,\n `applied to the replica and backed up by litestream. As such, shorter intervals`,\n `incur a higher number of backup storage writes and files managed (e.g. in s3),`,\n `while longer intervals result requiring a larger buffer for changes upstream `,\n `(e.g. per-replication slot wal records). The default value of 15 seconds targets`,\n `an s3 API cost of ~$1/month (not counting storage costs).`,\n ``,\n `This option only applies to litestream v5 backups. For v3 backups, use`,\n `{bold ZERO_LITESTREAM_INCREMENTAL_BACKUP_INTERVAL_MINUTES}.`,\n ],\n },\n\n restoreParallelism: {\n type: v.number().optional(() => 48),\n desc: [\n `The number of WAL files to download in parallel when performing the`,\n `initial restore of the replica from the backup.`,\n ],\n },\n\n multipartConcurrency: {\n type: v.number().optional(),\n desc: [\n `The number of parts (of size {bold --litestream-multipart-size} bytes)`,\n `to upload or download in parallel when backing up or restoring the snapshot.`,\n `Leave this unset to use 48, reduced as needed to keep the parts within`,\n `a quarter of the memory available to the container.`,\n ],\n },\n\n multipartSize: {\n type: v.number().optional(() => 16 * 1024 * 1024),\n desc: [\n `The size of each part when uploading or downloading the snapshot with`,\n `{bold --multipart-concurrency}. Note that up to {bold concurrency * size}`,\n `bytes of memory are used when backing up or restoring the snapshot.`,\n ],\n },\n },\n\n storageDBTmpDir: {\n type: v.string().optional(),\n desc: [\n `tmp directory for IVM operator storage. Leave unset to use os.tmpdir()`,\n ],\n },\n\n initialSync: {\n tableCopyWorkers: {\n type: v.number().optional(() => 5),\n desc: [\n `The number of parallel workers used to copy tables during initial sync.`,\n `Each worker uses a database connection and will buffer up to (approximately)`,\n `10 MB of table data in memory during initial sync. Increasing the number of`,\n `workers may improve initial sync speed; however, note that local disk throughput`,\n `(i.e. IOPS), upstream CPU, and network bandwidth may also be bottlenecks.`,\n ],\n },\n\n profileCopy: {\n type: v.boolean().optional(),\n hidden: true,\n desc: [\n `Takes a cpu profile during the copy phase initial-sync, storing it as a JSON file`,\n `initial-copy.cpuprofile in the tmp directory.`,\n ],\n },\n\n textCopy: {\n type: v.boolean().optional(() => false),\n desc: [\n `Use text-format COPY instead of binary COPY for initial sync and`,\n `backfill streaming. This is slower but can work around issues with`,\n `binary encoding of certain data types.`,\n ],\n },\n },\n\n shadowSync: {\n enabled: {\n type: v.boolean().optional(() => false),\n desc: [\n `Periodically exercises the initial-sync code path against a sample of`,\n `rows from every published table, writing to a throwaway SQLite database.`,\n `This acts as a canary: if the real initial-sync path ever breaks (schema`,\n `drift, PG version quirks, etc.), the shadow run fails before a customer`,\n `actually needs a full reset.`,\n ],\n },\n\n intervalHours: {\n type: v.number().optional(() => 12),\n desc: [\n `The interval between shadow initial-sync runs, in hours. The first`,\n `run fires within [2/3, 1) of this interval after startup, so the`,\n `canary completes at least once per task lifetime (the replication`,\n `manager is restarted every ~24h) while still jittering so a fleet`,\n `restart does not cause all tasks to canary simultaneously.`,\n ],\n },\n\n sampleRate: {\n type: v.number().optional(() => 0.1),\n desc: [\n `The BERNOULLI sampling rate for each table (0 < rate <= 1). A value of`,\n `1 disables sampling and copies all rows (still subject to`,\n `{bold max-rows-per-table}).`,\n ],\n },\n\n maxRowsPerTable: {\n type: v.number().optional(() => 10000),\n desc: [\n `The hard upper bound on rows copied per table per shadow run. Guards`,\n `against unexpectedly large tables consuming disk / upstream bandwidth.`,\n ],\n },\n },\n\n /** @deprecated */\n targetClientRowCount: {\n type: v.number().optional(() => 20_000),\n deprecated: [\n 'This option is no longer used and will be removed in a future version.',\n 'The client-side cache no longer enforces a row limit. Instead, TTL-based expiration',\n 'automatically manages cache size to prevent unbounded growth.',\n ],\n hidden: true,\n },\n\n lazyStartup: {\n type: v.boolean().optional(() => false),\n desc: [\n 'Delay starting the majority of zero-cache until first request.',\n '',\n 'This is mainly intended to avoid connecting to Postgres replication stream',\n 'until the first request is received, which can be useful i.e., for preview instances.',\n '',\n 'Currently only supported in single-node mode.',\n ],\n },\n\n serverVersion: {\n type: v.string().optional(),\n desc: [`The version string outputted to logs when the server starts up.`],\n },\n\n enableTelemetry: {\n type: v.boolean().optional(() => true),\n desc: [\n `Set to false to opt out of telemetry collection.`,\n ``,\n `This helps us improve Zero by collecting anonymous usage data.`,\n `Setting the DO_NOT_TRACK environment variable also disables telemetry.`,\n ],\n },\n\n cloudEvent: {\n sinkEnv: {\n type: v.string().optional(),\n desc: [\n `ENV variable containing a URI to a CloudEvents sink. When set, ZeroEvents`,\n `will be published to the sink as the {bold data} field of CloudEvents.`,\n `The {bold source} field of the CloudEvents will be set to the {bold ZERO_TASK_ID},`,\n `along with any extension attributes specified by the {bold ZERO_CLOUD_EVENT_EXTENSION_OVERRIDES_ENV}.`,\n ``,\n `This configuration is modeled to easily integrate with a knative K_SINK binding,`,\n `(i.e. https://github.com/knative/eventing/blob/main/docs/spec/sources.md#sinkbinding).`,\n `However, any CloudEvents sink can be used.`,\n ],\n },\n\n extensionOverridesEnv: {\n type: v.string().optional(),\n desc: [\n `ENV variable containing a JSON stringified object with an {bold extensions} field`,\n `containing attributes that should be added or overridden on outbound CloudEvents.`,\n ``,\n `This configuration is modeled to easily integrate with a knative K_CE_OVERRIDES binding,`,\n `(i.e. https://github.com/knative/eventing/blob/main/docs/spec/sources.md#sinkbinding).`,\n ],\n },\n },\n};\n\nexport type ZeroConfig = Config<typeof zeroOptions>;\n\nlet loadedConfig: Config<typeof zeroOptions> | undefined;\n\nexport function getZeroConfig(\n opts: Omit<ParseOptions, 'envNamePrefix'> = {},\n): ZeroConfig {\n if (!loadedConfig || singleProcessMode()) {\n loadedConfig = parseOptions(zeroOptions, {\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n emitDeprecationWarnings: false, // overridden at the top level parse\n ...opts,\n });\n\n if (loadedConfig.queryHydrationStats) {\n runtimeDebugFlags.trackRowCountsVended = true;\n }\n }\n return loadedConfig;\n}\n\n/**\n * Same as {@link getZeroConfig}, with an additional check that the\n * config has already been normalized (i.e. by the top level server/runner).\n */\nexport function getNormalizedZeroConfig(\n opts: Omit<ParseOptions, 'envNamePrefix'> = {},\n): NormalizedZeroConfig {\n const config = getZeroConfig(opts);\n assertNormalized(config);\n return config;\n}\n\n/**\n * Gets the server version from the config if provided. Otherwise it gets it\n * from the Zero package.json.\n */\nexport function getServerVersion(\n config: Pick<ZeroConfig, 'serverVersion'> | undefined,\n): string {\n return config?.serverVersion ?? packageJson.version;\n}\n\n/**\n * The access that a password grants to zero-cache's protected endpoints.\n * `admin` grants access to all of them. `operator` grants access only to the\n * ones that cannot expose application data (see `--operator-password`).\n */\nexport type AdminAccess = 'admin' | 'operator';\n\n/**\n * Returns whether `password` is the admin password. Endpoints that can expose\n * application data must use this, which never accepts the operator password.\n */\nexport function isAdminPasswordValid(\n lc: LogContext,\n config: Pick<NormalizedZeroConfig, 'adminPassword'>,\n password: string | undefined,\n): boolean {\n return getAccess(lc, config, undefined, password) === 'admin';\n}\n\n/**\n * Returns the access that `password` grants, accepting either the admin\n * password or the operator password, or `undefined` if it grants none.\n *\n * Only endpoints that cannot expose application data may use this, and they\n * must not serve anything to `operator` access that `--operator-password`\n * documents as withheld.\n */\nexport function getOperatorAccess(\n lc: LogContext,\n config: Pick<NormalizedZeroConfig, 'adminPassword' | 'operatorPassword'>,\n password: string | undefined,\n): AdminAccess | undefined {\n return getAccess(lc, config, config.operatorPassword, password);\n}\n\nfunction getAccess(\n lc: LogContext,\n {adminPassword}: Pick<NormalizedZeroConfig, 'adminPassword'>,\n operatorPassword: string | undefined,\n password: string | undefined,\n): AdminAccess | undefined {\n // If development mode, password is optional\n // We use process.env.NODE_ENV === 'development' as a sign that we're in\n // development mode, rather than a custom env var like ZERO_DEVELOPMENT_MODE,\n // because NODE_ENV is more standard and is already used by many tools.\n // Note that if NODE_ENV is not set, we assume production mode.\n\n if (!password && !adminPassword && isDevelopmentMode()) {\n warnOnce(\n lc,\n 'No admin password set; allowing access in development mode only',\n );\n return 'admin';\n }\n\n if (!adminPassword && !operatorPassword) {\n lc.warn?.('No admin password set; denying access');\n return undefined;\n }\n\n // Compare against both configured passwords (rather than stopping at the\n // first match) so that timing does not reveal which one matched.\n const isAdmin = passwordMatches(password, adminPassword);\n const isOperator = passwordMatches(password, operatorPassword);\n\n if (isAdmin) {\n lc.debug?.('Admin password accepted');\n return 'admin';\n }\n if (isOperator) {\n lc.debug?.('Operator password accepted');\n return 'operator';\n }\n lc.warn?.(\n operatorPassword\n ? 'Invalid admin or operator password'\n : 'Invalid admin password',\n );\n return undefined;\n}\n\nfunction passwordMatches(\n password: string | undefined,\n expected: string | undefined,\n): boolean {\n if (!expected) {\n return false;\n }\n\n // Use constant-time comparison to prevent timing attacks\n const passwordBuffer = Buffer.from(password ?? '');\n const expectedBuffer = Buffer.from(expected);\n\n // Handle length mismatch in constant time\n if (passwordBuffer.length !== expectedBuffer.length) {\n // Perform dummy comparison to maintain constant timing\n timingSafeEqual(expectedBuffer, expectedBuffer);\n return false;\n }\n\n return timingSafeEqual(passwordBuffer, expectedBuffer);\n}\n\nlet hasWarned = false;\n\nfunction warnOnce(lc: LogContext, msg: string) {\n if (!hasWarned) {\n lc.warn?.(msg);\n hasWarned = true;\n }\n}\n\n// For testing purposes - reset the warning state\nexport function resetWarnOnceState() {\n hasWarned = false;\n}\n"],"mappings":"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,MAAM,CAAC,8DAA8D;GACrE,QAAQ;EACV;EAEA,+BAA+B;GAC7B,MAAM,eAAE,OAAO,EAAE,eAAe,GAAI;GACpC,MAAM,CAAC,uDAAuD;GAC9D,QAAQ;EACV;EAEA,iCAAiC;GAC/B,MAAM,eAAE,OAAO,EAAE,eAAe,GAAO;GACvC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;GACF;GACA,QAAQ;EACV;EAEA,iCAAiC;GAC/B,MAAM,eAAE,OAAO,EAAE,eAAe,GAAI;GACpC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;EACF;EAEA,uCAAuC;GACrC,MAAM,eAAE,OAAO,EAAE,eAAe,CAAG;GACnC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;EACF;EAEA,6CAA6C;GAC3C,MAAM,eAAE,OAAO,EAAE,eAAe,EAAE;GAClC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;EACF;CACF;CAEA,QAAQ;EACN,MAAM,eAAE,OAAO,EAAE,SAAS;EAC1B,MAAM;GACJ;GACA;GACA;GACA;GACA;EACF;CACF;CAEA;CAEA,gBAAgB;EACd,MAAM,eAAE,OAAO,EAAE,SAAS;EAC1B,MAAM;GACJ;GACA;GACA;GACA;EACF;CACF;CAEA,WAAW;EACT,MAAM,eAAE,QAAQ,EAAE,eAAe,IAAI;EACrC,MAAM;GACJ;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;CACF;CAEA,gBAAgB;EACd,kBAAkB;GAChB,MAAM,eAAE,OAAO,EAAE,eAAe,GAAK;GACrC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;EA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"}
1
+ {"version":3,"file":"zero-config.js","names":[],"sources":["../../../../../zero-cache/src/config/zero-config.ts"],"sourcesContent":["/**\n * These types represent the _compiled_ config whereas `define-config` types represent the _source_ config.\n */\n\nimport {timingSafeEqual} from 'node:crypto';\nimport type {LogContext} from '@rocicorp/logger';\nimport {logOptions} from '../../../otel/src/log-options.ts';\nimport {\n flagToEnv,\n parseOptions,\n type Config,\n type ParseOptions,\n} from '../../../shared/src/options.ts';\nimport * as v from '../../../shared/src/valita.ts';\n// @circular-dep-ignore - importing package.json for version info only\nimport packageJson from '../../../zero/package.json' with {type: 'json'};\nimport {runtimeDebugFlags} from '../../../zql/src/builder/debug-delegate.ts';\nimport {singleProcessMode} from '../types/processes.ts';\nimport {\n ALLOWED_APP_ID_CHARACTERS,\n INVALID_APP_ID_MESSAGE,\n} from '../types/shards.ts';\nimport {DEFAULT_PREFERRED_PREFIXES} from './network.ts';\nimport {\n assertNormalized,\n isDevelopmentMode,\n type NormalizedZeroConfig,\n} from './normalize.ts';\nexport type {LogConfig} from '../../../otel/src/log-options.ts';\n\nexport const ZERO_ENV_VAR_PREFIX = 'ZERO_';\n\nexport const appOptions = {\n id: {\n type: v\n .string()\n .optional(() => 'zero')\n .assert(id => ALLOWED_APP_ID_CHARACTERS.test(id), INVALID_APP_ID_MESSAGE),\n desc: [\n 'Unique identifier for the app.',\n '',\n 'Multiple zero-cache apps can run on a single upstream database, each of which',\n 'is isolated from the others, with its own permissions, sharding (future feature),',\n 'and change/cvr databases.',\n '',\n 'The metadata of an app is stored in an upstream schema with the same name,',\n 'e.g. \"zero\", and the metadata for each app shard, e.g. client and mutation',\n 'ids, is stored in the \"\\\\{app-id\\\\}_\\\\{#\\\\}\" schema. (Currently there is only a single',\n '\"0\" shard, but this will change with sharding).',\n '',\n 'The CVR and Change data are managed in schemas named \"\\\\{app-id\\\\}_\\\\{shard-num\\\\}/cvr\"',\n 'and \"\\\\{app-id\\\\}_\\\\{shard-num\\\\}/cdc\", respectively, allowing multiple apps and shards',\n 'to share the same database instance (e.g. a Postgres \"cluster\") for CVR and Change management.',\n '',\n 'Due to constraints on replication slot names, an App ID may only consist of',\n 'lower-case letters, numbers, and the underscore character.',\n '',\n 'Note that this option is used by both {bold zero-cache} and {bold zero-deploy-permissions}.',\n ],\n },\n\n publications: {\n type: v.array(v.string()).optional(() => []),\n desc: [\n `Postgres {bold PUBLICATION}s that define the tables and columns to`,\n `replicate. Publication names may not begin with an underscore,`,\n `as zero reserves that prefix for internal use.`,\n ``,\n `If unspecified, zero-cache will create and use an internal publication that`,\n `publishes all tables in the {bold public} schema, i.e.:`,\n ``,\n `CREATE PUBLICATION _\\\\{app-id\\\\}_public_0 FOR TABLES IN SCHEMA public;`,\n ``,\n `Note that changing the set of publications will result in resyncing the replica,`,\n `which may involve downtime (replication lag) while the new replica is initializing.`,\n `To change the set of publications without disrupting an existing app, a new app`,\n `should be created.`,\n ],\n },\n};\n\nexport const shardOptions = {\n id: {\n type: v\n .string()\n .assert(() => {\n throw new Error(\n `ZERO_SHARD_ID is no longer an option. Please use ZERO_APP_ID instead.`,\n // TODO: Link to release / migration notes?\n );\n })\n .optional(),\n hidden: true,\n },\n\n num: {\n type: v.number().optional(() => 0),\n desc: [\n `The shard number (from 0 to NUM_SHARDS) of the App. zero will eventually`,\n `support data sharding as a first-class primitive; until then, deploying`,\n `multiple shard-nums creates functionally identical shards. Until sharding is`,\n `actually meaningful, this flag is hidden but available for testing.`,\n ],\n hidden: true,\n },\n};\n\nconst replicaOptions = {\n file: {\n type: v.string().optional(() => 'zero.db'),\n desc: [\n `File path to the SQLite replica that zero-cache maintains.`,\n `This can be lost, but if it is, zero-cache will have to re-replicate next`,\n `time it starts up.`,\n ],\n },\n\n vacuumIntervalHours: {\n type: v.number().optional(),\n desc: [\n `Performs a VACUUM at server startup if the specified number of hours has elapsed`,\n `since the last VACUUM (or initial-sync). The VACUUM operation is heavyweight`,\n `and requires double the size of the db in disk space. If unspecified, VACUUM`,\n `operations are not performed.`,\n ],\n },\n};\n\nexport type ReplicaOptions = Config<typeof replicaOptions>;\n\nconst perUserMutationLimit = {\n max: {\n type: v.number().optional(),\n desc: [\n `The maximum mutations per user within the specified {bold windowMs}.`,\n `If unset, no rate limiting is enforced.`,\n ],\n },\n windowMs: {\n type: v.number().optional(() => 60_000),\n desc: [\n `The sliding window over which the {bold perUserMutationLimitMax} is enforced.`,\n ],\n },\n};\n\nexport type RateLimit = Config<typeof perUserMutationLimit>;\n\nconst authOptions = {\n jwk: {\n type: v.string().optional(),\n desc: [\n `A public key in JWK format used to verify JWTs. Only one of {bold jwk}, {bold jwksUrl} and {bold secret} may be set.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n jwksUrl: {\n type: v.string().optional(),\n desc: [\n `A URL that returns a JWK set used to verify JWTs. Only one of {bold jwk}, {bold jwksUrl} and {bold secret} may be set.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n secret: {\n type: v.string().optional(),\n desc: [\n `A symmetric key used to verify JWTs. Only one of {bold jwk}, {bold jwksUrl} and {bold secret} may be set.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n issuer: {\n type: v.string().optional(),\n desc: [\n `Expected issuer ({bold iss} claim) for JWT validation.`,\n `If set, tokens with a different or missing issuer will be rejected.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n audience: {\n type: v.string().optional(),\n desc: [\n `Expected audience ({bold aud} claim) for JWT validation.`,\n `If set, tokens with a different or missing audience will be rejected.`,\n ],\n deprecated: [\n `Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`,\n ],\n },\n revalidateIntervalSeconds: {\n type: v.number().optional(() => 300),\n desc: [\n `The interval in seconds between periodic /query auth revalidation for validated connections.`,\n `If unset, periodic auth revalidation is disabled.`,\n ],\n },\n retransformIntervalSeconds: {\n type: v.number().optional(() => 300),\n desc: [\n `The interval in seconds between periodic shared /query retransform work for a client group.`,\n `If unset, periodic shared retransform is disabled.`,\n ],\n },\n};\n\nconst makeDeprecationMessage = (flag: string) =>\n `Use {bold ${flagToEnv(ZERO_ENV_VAR_PREFIX, flag)}} (or {bold --${flag}}) instead.`;\n\nconst makeMutatorQueryOptions = (\n replacement: 'mutate' | 'query' | undefined,\n suffix: string,\n) => ({\n url: {\n type: v.array(v.string()).optional(), // optional until we remove CRUD mutations\n desc: [\n `The URL of the API server to which zero-cache will ${suffix}.`,\n ``,\n `{bold IMPORTANT:} URLs are matched using {bold URLPattern}, a standard Web API.`,\n ``,\n `{bold Pattern Syntax:}`,\n ` URLPattern uses a simple and intuitive syntax similar to Express routes.`,\n ` Wildcards and named parameters make it easy to match multiple URLs.`,\n ``,\n `{bold Basic Examples:}`,\n ` Exact URL match:`,\n ` \"https://api.example.com/mutate\"`,\n ` `,\n ` Any subdomain using wildcard:`,\n ` \"https://*.example.com/mutate\"`,\n ` `,\n ` Multiple subdomain levels:`,\n ` \"https://*.*.example.com/mutate\"`,\n ` `,\n ` Any path under a domain:`,\n ` \"https://api.example.com/*\"`,\n ` `,\n ` Named path parameters:`,\n ` \"https://api.example.com/:version/mutate\"`,\n ` ↳ Matches \"https://api.example.com/v1/mutate\", \"https://api.example.com/v2/mutate\", etc.`,\n ``,\n `{bold Advanced Patterns:}`,\n ` Optional path segments:`,\n ` \"https://api.example.com/:path?\"`,\n ` `,\n ` Regex in segments (for specific patterns):`,\n ` \"https://api.example.com/:version(v\\\\\\\\d+)/mutate\"`,\n ` ↳ Matches only \"v\" followed by digits`,\n ``,\n `{bold Multiple patterns:}`,\n ` [\"https://api1.example.com/mutate\", \"https://api2.example.com/mutate\"]`,\n ``,\n `{bold Note:} Query parameters and URL fragments (#) are automatically ignored during matching.`,\n ``,\n `For full URLPattern syntax, see: https://developer.mozilla.org/en-US/docs/Web/API/URLPattern`,\n ],\n ...(replacement\n ? {deprecated: [makeDeprecationMessage(`${replacement}-url`)]}\n : {}),\n },\n apiKey: {\n type: v.string().optional(),\n desc: [\n `An optional secret used to authorize zero-cache to call the API server handling writes.`,\n ],\n ...(replacement\n ? {deprecated: [makeDeprecationMessage(`${replacement}-api-key`)]}\n : {}),\n },\n forwardCookies: {\n type: v.boolean().optional(() => false),\n desc: [\n `If true, zero-cache will forward cookies from the request.`,\n `This is useful for passing authentication cookies to the API server.`,\n `If false, cookies are not forwarded.`,\n ],\n ...(replacement\n ? {deprecated: [makeDeprecationMessage(`${replacement}-forward-cookies`)]}\n : {}),\n },\n allowedClientHeaders: {\n type: v.array(v.string()).optional(),\n desc: [\n `A list of header names that clients are allowed to set via custom headers.`,\n `If specified, only headers in this list will be forwarded to the ${suffix === 'push mutations' ? 'push' : 'query'} URL.`,\n `Header names are case-insensitive.`,\n `If not specified, no client-provided headers are forwarded.`,\n `Example: ZERO_${replacement ? replacement.toUpperCase() : suffix === 'push mutations' ? 'MUTATE' : 'QUERY'}_ALLOWED_CLIENT_HEADERS=x-request-id,x-correlation-id`,\n ],\n ...(replacement\n ? {\n deprecated: [\n makeDeprecationMessage(`${replacement}-allowed-client-headers`),\n ],\n }\n : {}),\n },\n allowedRequestHeaders: {\n type: v.array(v.string()).optional(),\n desc: [\n `A list of header names to forward from the incoming HTTP request to the ${suffix === 'push mutations' ? 'push' : 'query'} URL.`,\n `Unlike {bold allowed-client-headers} (which forwards headers set by the client), these are taken`,\n `from the HTTP request that established the connection (e.g. headers injected by a proxy or load balancer).`,\n `If a listed header is present on the request, its value is forwarded upstream under the same header name.`,\n `Header names are case-insensitive.`,\n `If not specified, no request headers are forwarded.`,\n `Example: ZERO_${replacement ? replacement.toUpperCase() : suffix === 'push mutations' ? 'MUTATE' : 'QUERY'}_ALLOWED_REQUEST_HEADERS=x-forwarded-for,cf-ray`,\n ],\n ...(replacement\n ? {\n deprecated: [\n makeDeprecationMessage(`${replacement}-allowed-request-headers`),\n ],\n }\n : {}),\n },\n});\n\nconst mutateOptions = makeMutatorQueryOptions(undefined, 'push mutations');\nconst pushOptions = makeMutatorQueryOptions('mutate', 'push mutations');\nconst queryOptions = makeMutatorQueryOptions(undefined, 'send synced queries');\nconst getQueriesOptions = makeMutatorQueryOptions(\n 'query',\n 'send synced queries',\n);\n\nexport type AuthConfig = Config<typeof authOptions>;\n\n/** @deprecated used only by legacy JWT verification helpers */\nexport type LegacyJWTAuthConfig = Pick<\n AuthConfig,\n 'jwk' | 'jwksUrl' | 'secret' | 'issuer' | 'audience'\n>;\n\n// Note: --help will list flags in the order in which they are defined here,\n// so order the fields such that the important (e.g. required) ones are first.\n// (Exported for testing)\nexport const zeroOptions = {\n upstream: {\n db: {\n type: v.string(),\n desc: [\n `The \"upstream\" authoritative postgres database.`,\n `In the future we will support other types of upstream besides PG.`,\n ],\n },\n\n type: {\n type: v.literalUnion('pg', 'custom').optional(() => 'pg'),\n desc: [\n `The meaning of the {bold upstream-db} depends on the upstream type:`,\n `* {bold pg}: The connection database string, e.g. \"postgres://...\"`,\n `* {bold custom}: The base URI of the change source \"endpoint, e.g.`,\n ` \"https://my-change-source.dev/changes/v0/stream?apiKey=...\"`,\n ],\n hidden: true, // TODO: Unhide when ready to officially support.\n },\n\n maxConns: {\n type: v.number().optional(() => 20),\n desc: [\n `The maximum number of connections to open to the upstream database`,\n `for committing mutations. This is divided evenly amongst sync workers.`,\n `In addition to this number, zero-cache uses one connection for the`,\n `replication stream.`,\n ``,\n `Note that this number must allow for at least one connection per`,\n `sync worker, or zero-cache will fail to start. See {bold num-sync-workers}`,\n ],\n },\n\n maxConnsPerWorker: {\n type: v.number().optional(),\n hidden: true, // Passed from main thread to sync workers\n },\n\n pgReplicationSlotFailover: {\n type: v.boolean().optional(),\n desc: [\n `For upstream Postgres versions 17+, creates replication slots with the`,\n `{bold failover} parameter set to {bold true} to enable slot synchronization`,\n `and failover. Note that additional Postgres-level configuration is necessary`,\n `when enabling this option. For details, see:`,\n ``,\n `https://www.postgresql.org/docs/current/logicaldecoding-explanation.html#LOGICALDECODING-REPLICATION-SLOTS-SYNCHRONIZATION`,\n ``,\n `(Note that this option has no effect for Postgres versions before 17.)`,\n ],\n },\n\n pgReplicationSlotPerReplica: {\n type: v.boolean().optional(() => false),\n desc: [\n `Creates a dedicated replication slot for each replication-manager, rather than`,\n `having a new replication-manager take over the slot of the one it replaces.`,\n ``,\n `A new replication-manager restores its replica from the backup, creates its own slot`,\n `and starts replicating from the head of the change-db's change log while the previous`,\n `replication-manager continues to serve. Once it has caught up to that head, it takes`,\n `over the change log. The replica's backup and the change-db remain compatible with`,\n `the default (shared slot) mode, so disabling this option does not trigger a resync.`,\n ``,\n `This is a rollback-safe intermediate step towards an upcoming high-availability mode,`,\n `in which multiple replication-managers run concurrently with their own slots, each`,\n `maintaining a local change log instead of the global change log in the change-db.`,\n `Running with this option first validates the per-replica slot setup, and rolling back`,\n `from high-availability mode to this configuration re-initializes the change-db's change`,\n `log from the replica rather than requiring a resync.`,\n ``,\n `Requires litestream v5 backups. Each slot retains upstream WAL until it is consumed or`,\n `dropped. Slots of replication-managers that are no longer running are dropped`,\n `automatically.`,\n ],\n },\n\n pgHighAvailabilityReplication: {\n type: v.boolean().optional(),\n desc: [\n `Runs replication-managers in high-availability mode, allowing multiple tasks to`,\n `run concurrently, each using their own replication slot and maintaining a local`,\n `change-log in sqlite.`,\n ``,\n `In this configuration, the PG change-streamer db is not used or maintained. Consequently`,\n `after running servers in high-availability mode, rolling back to a legacy singleton-mode task`,\n `will trigger a resync in order to re-intialize the PG change-streamer db.`,\n // Note: This is a feature flag that automatically enables the necessary\n // implementation flags:\n // ZERO_UPSTREAM_PG_REPLICATION_SLOT_PER_REPLICA = true\n // ZERO_LITESTREAM_BACKUP_USING_V5 = true,\n // ZERO_CHANGE_STREAMER_SQLITE_CHANGE_LOG_MODE = serve\n // ZERO_CHANGE_STREAMER_SQLITE_CHANGE_LOG_READ_PERCENT = 100\n // ZERO_CHANGE_STREAMER_SQLITE_CHANGE_LOG_COLD_READ_PERCENT = 100\n // ZERO_CHANGE_STREAMER_PG_CHANGE_LOG_ENABLED = false\n ],\n hidden: true, // TODO: Expose / roll out.\n },\n\n pgResumeOrphanedSlotGracePeriodMs: {\n type: v.number().optional(() => 20_000),\n desc: [\n `The grace period to wait before taking over an inactive replication slot, \"resuming\"`,\n `the replica. With high availability replication, a new replica is generally \"forked\"`,\n `from a running, active replica. Resumption happens as a last resort when no there are no`,\n `active replicas, as it carries the risk of stealing the slot from a task that is attempting`,\n `to reconnect to its slot.`,\n ``,\n `In local development, where it is often expected for slots to be inactive, it is reasonable to set`,\n `this to value to 0.`,\n ],\n hidden: true,\n },\n\n pgReplicationEpoch: {\n type: v.number().optional(() => 0),\n desc: [\n `Replication managers sharing the same epoch attempt to converge on a single`,\n `generation (i.e. the result of an initial-sync); if multiple tasks are started`,\n `simultaneously, they coordinate with each other such that one performs the`,\n `initial-sync while the others wait for it.`,\n ``,\n `Incrementing the epoch is the way to reliably force a resync; a replication manager`,\n `on a new epoch will ignore any replicas on other epochs.`,\n ``,\n `Note that changing the {bold ZERO_LITESTREAM_BACKUP_URL} generally achieves a resync`,\n `as well, but with high available replication managers, changing only the backup url can`,\n `lead to confusion if an old replication manager is performing initial sync, causing the`,\n `new replication manager to wait for it. Incrementing the replication epoch is recommended`,\n `instead.`,\n ],\n hidden: true,\n },\n\n // Temporary rollout gate. This defaults off for the compatibility\n // deployment; enable it after all replication managers can consume\n // partial-index schema snapshots.\n pgPartialIndexTriggers: {\n type: v.boolean().optional(() => false),\n hidden: true,\n },\n\n pgStreamInboundTimeoutMs: {\n type: v.number().optional(),\n desc: [\n `The time (in milliseconds) without any inbound message from the upstream`,\n `wal sender after which the replication stream is considered unresponsive`,\n `and torn down to force a reconnect.`,\n ``,\n `Defaults to 2x the server's {bold wal_sender_timeout}. That suits idle`,\n `streams, but a busy wal sender can be legitimately silent for longer —`,\n `e.g. while decoding through WAL from unpublished tables, or assembling a`,\n `large transaction that is only sent at commit. If the server's`,\n `{bold wal_sender_timeout} is aggressive (some managed environments`,\n `default it as low as 5 seconds), the resulting teardown aborts and`,\n `replays the in-flight transaction, which can prevent replication from`,\n `ever catching up on a large backlog. Set this option to widen the`,\n `client-side threshold without changing the server setting.`,\n ``,\n `(This option has no effect when {bold wal_sender_timeout} is 0, which`,\n `disables inbound liveness detection entirely.)`,\n ],\n },\n },\n\n /** @deprecated */\n push: pushOptions,\n mutate: mutateOptions,\n /** @deprecated */\n getQueries: getQueriesOptions,\n query: queryOptions,\n\n enableCrudMutations: {\n type: v.boolean().optional(() => true),\n desc: [\n `Enables support for legacy CRUD mutations. When this is {bold false}, no connections`,\n `are made from view-syncers to the upstream db, and push messages with CRUD mutations`,\n `result in an InvalidPush response.`,\n ],\n },\n\n allowLegacyQueries: {\n type: v.boolean().optional(() => false),\n desc: [\n `Allows clients to send legacy query ASTs directly to zero-cache.`,\n `Keep this disabled when using custom queries so that zero-cache rejects`,\n `client-supplied ASTs without parsing them.`,\n ],\n },\n\n cvr: {\n db: {\n type: v.string().optional(),\n desc: [\n `The Postgres database used to store CVRs. CVRs (client view records) keep track`,\n `of the data synced to clients in order to determine the diff to send on reconnect.`,\n `If unspecified, the {bold upstream-db} will be used.`,\n ],\n },\n\n maxConns: {\n type: v.number().optional(() => 30),\n desc: [\n `The maximum number of connections to open to the CVR database.`,\n `This is divided evenly amongst sync workers.`,\n ``,\n `Note that this number must allow for at least one connection per`,\n `sync worker, or zero-cache will fail to start. See {bold num-sync-workers}`,\n ],\n },\n\n maxConnsPerWorker: {\n type: v.number().optional(),\n hidden: true, // Passed from main thread to sync workers\n },\n\n garbageCollectionInactivityThresholdHours: {\n type: v.number().optional(() => 24 * 7),\n desc: [\n `The duration after which an inactive CVR is eligible for garbage collection.`,\n `Purging a CVR forces the next connection from that client group to`,\n `re-sync from scratch, so this should comfortably exceed how long a`,\n `typical user goes between sessions.`,\n `Note that garbage collection is an incremental, periodic process which does not`,\n `necessarily purge all eligible CVRs immediately.`,\n ],\n },\n\n garbageCollectionInitialIntervalSeconds: {\n type: v.number().optional(() => 60),\n desc: [\n `The initial interval at which to check and garbage collect inactive CVRs.`,\n `This interval is increased exponentially (up to 16 minutes) when there is`,\n `nothing to purge.`,\n ],\n },\n\n garbageCollectionInitialBatchSize: {\n type: v.number().optional(() => 25),\n desc: [\n `The initial number of CVRs to purge per garbage collection interval.`,\n `This number is increased linearly if the rate of new CVRs exceeds the rate of`,\n `purged CVRs, in order to reach a steady state.`,\n ``,\n `Setting this to 0 effectively disables CVR garbage collection.`,\n ],\n },\n },\n\n queryHydrationStats: {\n type: v.boolean().optional(),\n desc: [\n `Track and log the number of rows considered by query hydrations which`,\n `take longer than {bold log-slow-hydrate-threshold} milliseconds.`,\n `This is useful for debugging and performance tuning.`,\n ],\n },\n\n sqliteCorruptionChecks: {\n type: v.boolean().optional(() => false),\n desc: [\n `Run SQLite quick_check and integrity_check when corruption is detected.`,\n `These checks scan the replica and can take a long time on large databases.`,\n ],\n hidden: true,\n },\n\n snapshotRowCacheSize: {\n type: v.number().optional(() => 50_000),\n desc: [\n `The maximum number of entries in the per-worker cache of replica rows`,\n `read while advancing IVM pipelines. Every client group on a sync worker`,\n `reads the new and previous value of each replicated row change; the`,\n `cache lets the client groups on a worker share those reads. A replicated`,\n `transaction of N rows produces up to 2N entries.`,\n ``,\n `Setting this to 0 disables the cache.`,\n ],\n hidden: true,\n },\n\n enableQueryPlanner: {\n type: v.boolean().optional(() => true),\n desc: [\n `Enable the query planner for optimizing ZQL queries.`,\n ``,\n `The query planner analyzes and optimizes query execution by determining`,\n `the most efficient join strategies.`,\n ``,\n `You can disable the planner if it is picking bad strategies.`,\n ],\n },\n\n enableCorrelatedPredicatePushdown: {\n type: v.boolean().optional(() => true),\n desc: [\n `Copy a query's equality conditions on a relationship's join columns`,\n `into the related subquery. This reduces the rows that are read when a`,\n `change is pushed through the query.`,\n ``,\n `This is a kill switch. It will be removed.`,\n ],\n hidden: true,\n },\n\n enablePlannerAwarePushdown: {\n type: v.boolean().optional(() => true),\n desc: [\n `Copy the conditions of correlated predicate pushdown before the query`,\n `planner runs instead of after, so that the planner can use them. This`,\n `can change the plans that the planner picks.`,\n ``,\n `Has no effect when correlated predicate pushdown is off.`,\n ],\n hidden: true,\n },\n\n enableQueryCovering: {\n type: v.boolean().optional(() => true),\n desc: [\n `Enable shadow-mode query covering detection during query hydration.`,\n ``,\n `When enabled, view-syncers compare newly hydrated queries against running`,\n `queries with the same root table and log aggregate coverage stats.`,\n ``,\n `You can disable this if covering detection adds too much CPU overhead.`,\n ],\n },\n\n deferIvmWrites: {\n type: v.boolean().optional(() => true),\n desc: [\n `Derive IVM advancements without writing to the replica snapshot.`,\n ``,\n `A view-syncer normally makes each change durable in the SQLite snapshot`,\n `it is reading from, because the next change has to read a base that`,\n `includes the previous ones. Those writes are always rolled back -- the`,\n `replicator is the only committer -- so they exist only to serve reads`,\n `for the rest of the advancement.`,\n ``,\n `When enabled (the default), the changes are held in memory and merged`,\n `into each leaf scan instead, leaving the snapshot read-only, within the`,\n `budget set by {bold deferIvmWritesHeapProportion}. Disable it to write`,\n `every advancement through to the snapshot. The two modes are required`,\n `to be indistinguishable to the pipelines above the source.`,\n ],\n hidden: true,\n },\n\n deferIvmWritesHeapProportion: {\n type: v\n .number()\n .assert(\n value => value > 0 && value <= 1,\n 'must be greater than 0 and at most 1',\n )\n .optional(() => 0.25),\n desc: [\n `With {bold deferIvmWrites}, the proportion of {bold --max-old-space-size}`,\n `that the client groups of one sync worker may hold in memory at once.`,\n `Each client group holds its own copy of the changes it is advancing`,\n `through. Before an advancement starts, the number of rows it will`,\n `change is reserved from this budget, at an assumed 1 KiB per row; an`,\n `advancement that does not fit is written`,\n `through to the replica snapshot instead, as when {bold deferIvmWrites}`,\n `is off. The bytes the rows are estimated to hold are also added up as`,\n `the client groups go, and a client group that takes the total past the`,\n `budget writes the rows it holds through to the replica snapshot, and`,\n `the rest of its changes after them.`,\n ],\n hidden: true,\n },\n\n yieldThresholdMs: {\n type: v.number().optional(() => 10),\n desc: [\n `The maximum amount of time in milliseconds that a sync worker will`,\n `spend in IVM (processing query hydration and advancement) before yielding`,\n `to the event loop. Lower values increase responsiveness and fairness at`,\n `the cost of reduced throughput.`,\n ],\n },\n\n viewSyncerHydrationBudgetMs: {\n type: v\n .number()\n .assert(\n value => Number.isSafeInteger(value) && value >= 0,\n 'must be a nonnegative integer',\n )\n .optional(() => 0),\n desc: [\n `The soft time budget in milliseconds for hydrating inactive queries`,\n `during a view-syncer hydration pass. Active and internal queries always`,\n `finish, and time spent in custom-query transform round trips is not`,\n `charged to the budget. An inactive query not reached before the budget`,\n `is spent is evicted: its CVR record and the remaining TTL that would`,\n `have kept it warm are both dropped. A value of 0 disables`,\n `hydration-budget eviction.`,\n ],\n },\n\n viewSyncerQueryHydrationTimeoutMs: {\n type: v\n .number()\n .assert(\n value => Number.isSafeInteger(value) && value >= 0,\n 'must be a nonnegative integer',\n )\n .optional(() => 0),\n desc: [\n `The maximum processing time in milliseconds that a view-syncer spends`,\n `hydrating a single client query. Time spent yielding to other work is`,\n `not counted. A query whose hydration exceeds this limit is aborted and`,\n `removed from the client's view, and affected clients receive an error`,\n `for the query. The query is then rejected without being run again for`,\n `a cooldown period, after which a retry is allowed. Internal queries are`,\n `never aborted. A value of 0 disables the limit.`,\n ],\n },\n\n change: {\n db: {\n type: v.string().optional(),\n desc: [\n `The Postgres database used to store recent replication log entries, in order`,\n `to sync multiple view-syncers without requiring multiple replication slots on`,\n `the upstream database. If unspecified, the {bold upstream-db} will be used.`,\n ],\n },\n\n /** @deprecated */\n maxConns: {\n type: v.number().optional(() => 5),\n deprecated: [\n `Connections to the change db are created dynamically for subscriber catchup. Ensure`,\n `that the database supports sufficient connections for at least 5 + numViewSyncers.`,\n ],\n hidden: true,\n },\n\n statementTimeoutMs: {\n type: v.number().optional(() => 30_000),\n desc: [\n `Fail change-log db operations that make no progress within the specified timeout. This`,\n `differs from a postgres {bold statement_timeout} in that it is implemented to handle a`,\n `pathological case in which Postgres does not return a response but otherwise believes the`,\n `connection to be idle (e.g. a half-open connection).`,\n ],\n hidden: true, // make visible if proven to be effective/necessary\n },\n\n logBatchSize: {\n type: v\n .number()\n .assert(\n n => Number.isInteger(n) && n >= 1,\n `change.logBatchSize must be an integer >= 1`,\n )\n .optional(() => 2000),\n desc: [\n `The maximum number of change-log rows written per multi-row INSERT to the change`,\n `database. Larger upstream transactions are persisted in batches of this size rather`,\n `than one INSERT per change, which is the dominant cost when replicating large`,\n `transactions (e.g. bulk backfills or migrations). Larger values increase throughput`,\n `at the cost of higher transient memory; the effective batch is internally capped to`,\n `stay within Postgres's bind-parameter limit. Set to {bold 1} to disable batching.`,\n ],\n hidden: true, // make visible if proven to be effective/necessary\n },\n },\n\n replica: replicaOptions,\n\n log: logOptions,\n\n app: appOptions,\n\n shard: shardOptions,\n\n auth: authOptions,\n\n port: {\n type: v.number().optional(() => 4848),\n desc: [`The port for sync connections.`],\n },\n\n keepaliveTimeoutMs: {\n type: v.number().optional(),\n desc: [\n `The timeout since the last /keepalive request after which the server will initiate`,\n `a graceful shutdown. This is a workaround for AWS Elastic Container Service, which`,\n `otherwise provides no signal that a target has been deregistered (and should thus begin`,\n `shutdown); the cessation of health checks at /keepalive is instead used as the signal to`,\n `drain. (ECS later sends a SIGTERM before killing the server but only allows a 30-second`,\n `timeout before sending SIGKILL).`,\n ``,\n `Other container runners explicitly send a SIGTERM followed by a configurable drain interval,`,\n `in which case /keepalive logic is not necessary.`,\n ``,\n `When running the server in ECS, this timeout should be set to some multiple of the health`,\n `check interval. If the option is unset, the keepalive timeout is disabled in non-ECS environments,`,\n `and defaults to 20 seconds when run in ECS (determined by the presence of the`,\n `{bold ECS_CONTAINER_METADATA_URI_V4} environment variable as per`,\n `https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-environment-variables.html).`,\n ],\n },\n\n changeStreamer: {\n uri: {\n type: v.string().optional(),\n desc: [\n `When set, connects to the {bold change-streamer} at the given URI.`,\n `In a multi-node setup, this should be specified in {bold view-syncer} options,`,\n `pointing to the {bold replication-manager} URI, which runs a {bold change-streamer}`,\n `on port 4849.`,\n ],\n },\n\n mode: {\n type: v.literalUnion('dedicated', 'discover').optional(() => 'dedicated'),\n desc: [\n `As an alternative to {bold ZERO_CHANGE_STREAMER_URI}, the {bold ZERO_CHANGE_STREAMER_MODE}`,\n `can be set to \"{bold discover}\" to instruct the {bold view-syncer} to connect to the `,\n `ip address registered by the {bold replication-manager} upon startup.`,\n ``,\n `This may not work in all networking configurations, e.g. certain private `,\n `networking or port forwarding configurations. Using the {bold ZERO_CHANGE_STREAMER_URI}`,\n `with an explicit routable hostname is recommended instead.`,\n ``,\n `Note: This option is ignored if the {bold ZERO_CHANGE_STREAMER_URI} is set.`,\n ],\n },\n\n port: {\n type: v.number().optional(),\n desc: [\n `The port on which the {bold change-streamer} runs. This is an internal`,\n `protocol between the {bold replication-manager} and {bold view-syncers}, which`,\n `runs in the same process tree in local development or a single-node configuration.`,\n ``,\n `If unspecified, defaults to {bold --port} + 1.`,\n ],\n },\n\n /** @deprecated */\n address: {\n type: v.string().optional(),\n deprecated: [\n `Set the {bold ZERO_CHANGE_STREAMER_URI} on view-syncers instead.`,\n ],\n hidden: true,\n },\n\n /** @deprecated */\n protocol: {\n type: v.literalUnion('ws', 'wss').optional(() => 'ws'),\n deprecated: [\n `Set the {bold ZERO_CHANGE_STREAMER_URI} on view-syncers instead.`,\n ],\n hidden: true,\n },\n\n discoveryInterfacePreferences: {\n type: v.array(v.string()).optional(() => [...DEFAULT_PREFERRED_PREFIXES]),\n desc: [\n `The name prefixes to prefer when introspecting the network interfaces to determine`,\n `the externally reachable IP address for change-streamer discovery. This defaults`,\n `to commonly used names for standard ethernet interfaces in order to prevent selecting`,\n `special interfaces such as those for VPNs.`,\n ],\n // More confusing than it's worth to advertise this. The default list should be\n // adjusted to make things work for all environments; it is controlled as a\n // hidden flag as an emergency to unblock people with outlier network configs.\n hidden: true,\n },\n\n startupDelayMs: {\n type: v.number().optional(() => 15000),\n desc: [\n `The delay to wait before the change-streamer takes over the replication stream`,\n `(i.e. the handoff during replication-manager updates), to allow loadbalancers to register`,\n `the task as healthy based on healthcheck parameters. Note that if a change stream request`,\n `is received during this interval, the delay will be canceled and the takeover will happen`,\n `immediately, since the incoming request indicates that the task is registered as a target.`,\n ],\n },\n\n sqliteChangeLogMode: {\n type: v\n .literalUnion('off', 'write', 'compare', 'serve')\n .optional(() => 'off'),\n desc: [\n `Controls the staged SQLite change-log rollout. Modes are cumulative:`,\n `{bold off}, {bold write}, {bold compare}, and {bold serve}.`,\n ],\n hidden: true,\n },\n\n pgChangeLogEnabled: {\n type: v.boolean().optional(() => true),\n desc: [\n `Whether the legacy Postgres change log remains authoritative for`,\n `stream initialization, persistence, catchup, and upstream ACKs.`,\n `Disabling it requires SQLite serve mode at 100 percent and a v5 backup.`,\n ],\n hidden: true,\n },\n\n sqliteChangeLogReadPercent: {\n type: v.number().optional(() => 0),\n desc: [\n `The stable percentage of eligible catchup subscriptions served from SQLite.`,\n ],\n hidden: true,\n },\n\n sqliteChangeLogColdReadPercent: {\n type: v.number().optional(() => 0),\n desc: [\n `The stable percentage of eligible catchup subscriptions served from a`,\n `SQLite change log that is younger than its retention window, i.e. one`,\n `seeded less than {bold --change-streamer-sqlite-change-log-retention-ms}`,\n `ago. Selection uses the same hash as`,\n `{bold --change-streamer-sqlite-change-log-read-percent}, so a task that`,\n `serves cold is always one that would serve warm.`,\n ],\n hidden: true,\n },\n\n sqliteChangeLogComparePercent: {\n type: v.number().optional(() => 1),\n desc: [\n `The stable percentage of committed transactions whose catchup output is`,\n `compared between the Postgres and SQLite change logs in {bold compare} mode.`,\n ],\n hidden: true,\n },\n\n sqliteChangeLogRetentionMs: {\n type: v.number().optional(() => 60_000),\n desc: [`The minimum time window retained in the SQLite change log.`],\n hidden: true,\n },\n\n sqliteChangeLogReadBatchRows: {\n type: v.number().optional(() => 1000),\n desc: [`The target number of rows in each SQLite catchup read batch.`],\n hidden: true,\n },\n\n sqliteChangeLogPurgeBatchRows: {\n type: v.number().optional(() => 1000),\n desc: [`The target number of rows in each SQLite purge batch.`],\n hidden: true,\n },\n\n sqliteChangeLogBarrierTimeoutMs: {\n type: v.number().optional(() => 300_000),\n desc: [\n `The maximum wait for the SQLite required-head barrier. This is a`,\n `backstop for a wedged replica on an idle shard, where waiting costs`,\n `nothing and would otherwise go unnoticed. A shard with traffic is`,\n `bounded well before this by the subscriber's backlog reaching its`,\n `high water mark, which is the point at which waiting starts holding`,\n `up replication.`,\n ],\n hidden: true,\n },\n\n backPressureLimitHeapProportion: {\n type: v.number().optional(() => 0.04),\n desc: [\n `The percentage of {bold --max-old-space-size} to use as a buffer for absorbing replication`,\n `stream spikes. When the estimated amount of queued data exceeds this threshold, back pressure`,\n `is applied to the replication stream, delaying downstream sync as a result.`,\n ``,\n `The threshold was determined empirically with load testing. Higher thresholds have resulted`,\n `in OOMs. Note also that the byte-counting logic in the queue is strictly an underestimate of`,\n `actual memory usage (but importantly, proportionally correct), so the queue is actually`,\n `using more than what this proportion suggests.`,\n ``,\n `This parameter is exported as an emergency knob to reduce the size of the buffer in the`,\n `event that the server OOMs from back pressure. Resist the urge to {italic increase} this`,\n `proportion, as it is mainly useful for absorbing periodic spikes and does not meaningfully`,\n `affect steady-state replication throughput; the latter is determined by other factors such`,\n `as object serialization and PG throughput`,\n ``,\n `In other words, the back pressure limit does not constrain replication throughput;`,\n `rather, it protects the system when the upstream throughput exceeds the downstream`,\n `throughput.`,\n ],\n },\n\n flowControlConsensusTimeoutProportion: {\n type: v.number().optional(() => 4.0),\n desc: [\n `During periodic flow control checks (every 64kb), the amount of time to wait after the majority`,\n `of subscribers have acked, proportional to that interval, after which replication will continue`,\n `even if some subscribers have yet to ack.`,\n ``,\n `This allows a bounded amount of time for backlogged subscribers to catch up on each flush`,\n `without forcing all subscribers to wait for the entire backlog to be processed. It is also`,\n `useful for mitigating the effect of unresponsive subscribers due to severed websocket`,\n `connections or pathological zombie situations (until liveness checks or laggard detection`,\n `disconnects them).`,\n ``,\n `For example, if the majority of subscribers ack a message in 2.5ms, a padding proportion of`,\n `1.0 instructs replication to continue after an additional 2.5ms; for a proportion of 2.0, an`,\n `additional 5.0ms, etc. The default value of 4.0 allows for a subscriber to be 5x slower than the`,\n `majority in the steady state, while similarly bounding the extent to which a temporarily lagging`,\n `subscriber (e.g. due to catchup) slows down the fleet.`,\n ``,\n `Note that subscribers that continually exceed the timeout will eventually be disconnected and`,\n `instructed to shutdown in order to protect the healthy subscribers. It is thus important that`,\n `the proportion account for expected variance in processing speed across subscribers.`,\n ``,\n `Set this to a negative number to disable early flow control releases. (Not recommended, but`,\n `available as an emergency measure.)`,\n ],\n },\n\n flowControlSlowSubscriberGracePeriodSeconds: {\n type: v.number().optional(() => 30),\n desc: [\n `The period of time after which a lagging subscriber is disconnected and instructed to`,\n `restart. A subscriber is considered lagging if it {italic continuously} (1) exceeds the`,\n `consensus timeout and (2) fails to exceed the change rate of healthy subscribers. These`,\n `conditions distinguish expected, temporary periods of slowness from pathological`,\n `scenarios, such as zombie tasks, in which the subscriber is unlikely to recover.`,\n ``,\n `In particular, the second condition excludes subscribers that are performing initial`,\n `catchup, as the rate of change for catchup must eventually exceed the rate of upstream`,\n `changes. Note, however, that catchup rate can be legitimately slow during (rare) expensive`,\n `operations such as index creation.`,\n ``,\n `Thus, this grace period caps the amount of time that a lagging subscriber degrades overall`,\n `throughput, but should be long enough to allow for legitimate intervals of slowness.`,\n ``,\n `Note that in the pathological case where a catchup operation exceeds this grace period,`,\n `the system will eventually recover after the next backup/restore cycle, as the expensive`,\n `operation (e.g. index creation) will have been applied to the restored replica and no longer`,\n `executed during catchup.`,\n ``,\n `Set this to 0 or a negative number to disable laggard detection. (Not recommended, but`,\n `available as an emergency measure.)`,\n ],\n },\n },\n\n taskID: {\n type: v.string().optional(),\n desc: [\n `Globally unique identifier for the zero-cache instance.`,\n ``,\n `Setting this to a platform specific task identifier can be useful for debugging.`,\n `If unspecified, zero-cache will attempt to extract the TaskARN if run from within`,\n `an AWS ECS container, and otherwise use a random string.`,\n ],\n },\n\n perUserMutationLimit,\n\n numSyncWorkers: {\n type: v.number().optional(),\n desc: [\n `The number of processes to use for view syncing.`,\n `Leave this unset to use the maximum available parallelism.`,\n `If set to 0, the server runs without sync workers, which is the`,\n `configuration for running the {bold replication-manager}.`,\n ],\n },\n\n autoReset: {\n type: v.boolean().optional(() => true),\n desc: [\n `Automatically wipe and resync the replica when replication is halted.`,\n `This situation can occur for configurations in which the upstream database`,\n `provider prohibits event trigger creation, preventing the zero-cache from`,\n `being able to correctly replicate schema changes. For such configurations,`,\n `an upstream schema change will instead result in halting replication with an`,\n `error indicating that the replica needs to be reset.`,\n ``,\n `When {bold auto-reset} is enabled, zero-cache will respond to such situations`,\n `by shutting down, and when restarted, resetting the replica and all synced `,\n `clients. This is a heavy-weight operation and can result in user-visible`,\n `slowness or downtime if compute resources are scarce.`,\n ],\n },\n\n replicationLag: {\n reportIntervalMs: {\n type: v.number().optional(() => 10000),\n desc: [\n `The approximate interval at which replication lag reports are written upstream and`,\n `reported via the {bold zero.replication.total_lag} opentelemetry metric. If`,\n `an expected report is not received before the next interval, Zero retries with`,\n `a new report and increments {bold zero.replication.lag_report_retries}.`,\n ``,\n `Note that the interval is approximate and scheduled with ~1 second jitter to allow`,\n `multiple replication-managers (in RMv2) to cooperatively share the same reports.`,\n ``,\n `When enabled, lag reports are used to gate readiness of servers coming online by waiting`,\n `for lag to fall below the {bold ZERO_REPLICATION_LAG_INITIAL_READINESS_THRESHOLD_MS}.`,\n `As such, the reporting interval determines the time for which a new server waits for`,\n `the next report to determine readiness.`,\n ``,\n `A negative or 0 value disables lag reporting and the associated readiness gating.`,\n ``,\n `This feature is only supported on the postgres upstream type.`,\n ],\n },\n\n initialReadinessThresholdMs: {\n type: v.number().optional(() => 1000),\n desc: [\n `The maximum replication lag in milliseconds that a server is allowed to have`,\n `before it advertises readiness (to serve traffic). This prevents the server`,\n `from serving stale data to clients when it is first started.`,\n ``,\n `Note that this is an initial readiness gate only. Once the server announces readiness,`,\n `it will continue to serve traffic even if the replication lag exceeds this threshold`,\n `thereafter.`,\n ``,\n `When lag reporting is disabled, readiness is not gated by replication lag.`,\n ],\n },\n\n maxReadinessDelayMs: {\n type: v.number().optional(() => 600_000), // 10 minutes\n desc: [\n `The maximum time in milliseconds that a server will wait for replication lag`,\n `to fall below the {bold ZERO_REPLICATION_LAG_INITIAL_READINESS_THRESHOLD_MS}`,\n `before it announces readiness. This prevents the server from waiting indefinitely`,\n `for lag to fall below the threshold, which can occur if the upstream database`,\n `is under heavy load or if there is a network partition.`,\n ],\n },\n },\n\n adminPassword: {\n type: v.string().optional(),\n desc: [\n `A password used to administer zero-cache server, for example to access the`,\n `/statz endpoint.`,\n '',\n 'A password is optional in development mode but {bold required in production} mode.',\n '',\n 'The admin password also grants access to everything that the',\n '{bold operator-password} does.',\n ],\n },\n\n operatorPassword: {\n type: v.string().optional(),\n desc: [\n `A password that grants access only to the diagnostic endpoints that cannot`,\n `expose application data, so that people who operate zero-cache can`,\n `diagnose it without being able to read the data it serves. These are:`,\n '',\n `* {bold /profz} and {bold /profrmz}: CPU profiles. Profiles served for the`,\n ` operator password have the source of every regular expression redacted,`,\n ` since those can contain LIKE patterns from client queries.`,\n `* {bold /statz}: counts and sizes.`,\n `* {bold /plannerz}: the replica's schema and planner statistics.`,\n '',\n `All other protected endpoints (the inspector and {bold /heapz}) still`,\n `require the {bold admin-password}.`,\n '',\n `For {bold /profrmz} in a multi-node deployment, the replication-manager`,\n `must be configured with the same operator password.`,\n '',\n `If it is the same as the {bold admin-password}, it grants admin access.`,\n ],\n },\n\n websocketCompression: {\n type: v.boolean().optional(() => false),\n desc: [\n 'Enable WebSocket per-message deflate compression.',\n '',\n 'Compression can reduce bandwidth usage for sync traffic but',\n 'increases CPU usage on both client and server. Disabled by default.',\n '',\n 'See: https://github.com/websockets/ws#websocket-compression',\n ],\n },\n\n websocketCompressionOptions: {\n type: v.string().optional(),\n desc: [\n 'JSON string containing WebSocket compression options.',\n '',\n 'Only used if websocketCompression is enabled.',\n '',\n 'Example: \\\\{\"zlibDeflateOptions\":\\\\{\"level\":3\\\\},\"threshold\":1024\\\\}',\n '',\n 'See https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback for available options.',\n ],\n },\n\n websocketMaxPayloadBytes: {\n type: v.number().optional(() => 10 * 1024 * 1024),\n desc: [\n 'Maximum size of incoming WebSocket messages in bytes.',\n '',\n 'Messages exceeding this limit are rejected before parsing.',\n 'Default: 10MB (10 * 1024 * 1024 = 10485760)',\n ],\n },\n\n litestream: {\n executable: {\n type: v.string().optional(),\n desc: [\n `Path to the {bold litestream} executable. This must be built from the`,\n `{bold rocicorp/litestream} fork. Support for the official binary at v0.5.x`,\n `is planned.`,\n ],\n },\n\n executableV5: {\n type: v.string().optional(),\n desc: [\n `The v0.5.x litestream executable which is used for restoring the backup`,\n `backup when {bold ZERO_LITESTREAM_RESTORE_USING_V5} is specified.`,\n `litestream v0.5.8+ can restore from both v0.3.x and v0.5.x backup formats,`,\n `affording forwards compatibility with a future zero-cache`,\n `version that will use litestream v0.5.x to backup the replica.`,\n ],\n },\n\n restoreUsingV5: {\n type: v.boolean().optional(() => true),\n desc: [\n `Restores the backup using the {bold ZERO_LITESTREAM_EXECUTABLE_V5} if specified.`,\n `This provides a recovery path if rolling back from {bold ZERO_LITESTREAM_BACKUP_USING_V5}`,\n `as v5 restores from both v3 and v5 backups (whichever is more recent).`,\n ],\n },\n\n backupUsingV5: {\n type: v.boolean().optional(() => true),\n desc: [\n `Backs up the replica using Litestream v0.5.x. This is required for (upcoming)`,\n `high-availability replication. Set to false to revert to Litestream v0.3.x backups.`,\n ``,\n `zero-cache requests an incremental backup every`,\n `{bold ZERO_LITESTREAM_INCREMENTAL_BACKUP_INTERVAL_SECONDS} and only acknowledges`,\n `changes upstream once a backup containing them has completed.`,\n ``,\n `Litestream v0.5.x allows only one writer per backup location, so each`,\n `replication-manager backs up to its own subfolder of the backup URL. Subfolders`,\n `left by previous replication-managers are not cleaned up automatically; that is`,\n `up to the operator. The simplest approach is a lifecycle expiration rule on the`,\n `object store (e.g. S3). Every file needed for a restore is at most about`,\n `{bold ZERO_LITESTREAM_SNAPSHOT_BACKUP_INTERVAL_HOURS} old, so an expiration of at`,\n `least twice that interval is safe.`,\n ``,\n `Requires {bold ZERO_LITESTREAM_RESTORE_USING_V5} (enabled by default).`,\n ],\n },\n\n forkBackup: {\n type: v.boolean().optional(() => true), // TODO: Vet and make non-optional\n hidden: true,\n desc: [\n `When a replication-manager restores from another replication-manager's`,\n `backup, also copies the restored backup files into its own (new) backup`,\n `subfolder, so that its first backup continues incrementally instead of`,\n `uploading a full snapshot of the replica.`,\n ``,\n `This only works with a {bold ZERO_LITESTREAM_EXECUTABLE_V5} that supports`,\n `{bold restore -fork-to-url}. The flag is ignored if {bold ZERO_LITESTREAM_BACKUP_USING_V5}`,\n `is disabled.`,\n ],\n },\n\n configPath: {\n type: v.string().optional(() => './src/services/litestream/config.yml'),\n desc: [\n `Path to the litestream yaml config file. zero-cache will run this with its`,\n `environment variables, which can be referenced in the file via $\\\\{ENV\\\\}`,\n `substitution, for example:`,\n `* {bold ZERO_REPLICA_FILE} for the db path`,\n `* {bold ZERO_LITESTREAM_BACKUP_LOCATION} for the db replica url`,\n `* {bold ZERO_LITESTREAM_LOG_LEVEL} for the log level`,\n `* {bold ZERO_LOG_FORMAT} for the log type`,\n ],\n },\n\n configPathV5: {\n type: v\n .string()\n .optional(() => './src/services/litestream/config-v5.yml'),\n desc: [\n `Path to the litestream v5 yaml config file. zero-cache will run this with its`,\n `environment variables, which can be referenced in the file via $\\\\{ENV\\\\}`,\n `substitution, for example:`,\n `* {bold ZERO_REPLICA_FILE} for the db path`,\n `* {bold ZERO_LITESTREAM_BACKUP_LOCATION} for the db replica url`,\n `* {bold ZERO_LITESTREAM_LOG_LEVEL} for the log level`,\n `* {bold ZERO_LOG_FORMAT} for the log type`,\n ],\n },\n\n logLevel: {\n type: v\n .literalUnion('debug', 'info', 'warn', 'error')\n .optional(() => 'warn'),\n },\n\n backupURL: {\n type: v.string().optional(),\n desc: [\n `The location of the litestream backup, usually an {bold s3://} URL.`,\n `This is only consulted by the {bold replication-manager}.`,\n `{bold view-syncers} receive this information from the {bold replication-manager}.`,\n ],\n },\n\n backupURLOverride: {\n type: v.string().optional(),\n desc: [`Overrides the backup URL when present.`],\n hidden: true, // internal use\n },\n\n endpoint: {\n type: v.string().optional(),\n desc: [\n `The S3-compatible endpoint URL to use for the litestream backup. Only required for non-AWS services.`,\n `The {bold replication-manager} and {bold view-syncers} must have the same endpoint.`,\n ],\n },\n\n region: {\n type: v.string().optional(),\n desc: [\n `The AWS region for the litestream backup bucket. Required for non-standard AWS partitions`,\n `(e.g. GovCloud {bold us-gov-west-1}) where Litestream cannot auto-detect the region.`,\n `The {bold replication-manager} and {bold view-syncers} must have the same region.`,\n ],\n },\n\n port: {\n type: v.number().optional(),\n desc: [\n `Port on which litestream exports metrics, used to determine the replication`,\n `watermark up to which it is safe to purge change log records.`,\n ``,\n `If unspecified, defaults to {bold --port} + 2.`,\n ],\n },\n\n checkpointThresholdMB: {\n type: v.number().optional(() => 40),\n desc: [\n `The size of the WAL file at which litestream performs background, best-effort (PASSIVE)`,\n `SQLite checkpoints to apply the writes in the WAL to the main database file. Checkpoints`,\n `result in new WAL (v3) or LTS (v5) files that are then backed up asynchronously.`,\n ``,\n `Note that these PASSIVE checkpoints are skipped if a write is in progress, so high writes rates`,\n `can precipitate runaway wal growth. Also see {bold ZERO_LITESTREAM_FORCE_CHECKPOINT_THRESHOLD_MB}`,\n ],\n },\n\n minCheckpointPageCount: {\n type: v.number().optional(),\n deprecated: [`Use {bold ZERO_CHECKPOINT_THRESHOLD_MB}`],\n hidden: true,\n },\n\n maxCheckpointPageCount: {\n type: v.number().optional(),\n desc: [\n `The WAL page count at which SQLite performs a RESTART checkpoint, which`,\n `blocks writers until complete. Defaults to {bold minCheckpointPageCount * 10}.`,\n `Set to {bold 0} to disable RESTART checkpoints entirely.`,\n ``,\n `This setting is only relevant when replicating with litestream v3, and is ignored`,\n `when replicating with litestream v5.`,\n ],\n },\n\n forceCheckpointThresholdMB: {\n type: v.number().optional(() => 256),\n desc: [\n `The size of the WAL file at which to pause writes and explicitly initiate a`,\n `local litestream sync. This is a safeguard for the situation in which litestream's`,\n `background checkpoints continually defer to incoming writes (i.e. high write load).`,\n ``,\n `If the WAL size reaches the forced checkpoint threshold, writes pause for an`,\n `an explicit litestream checkpoint, providing a flow-control mechanism to ensure timely`,\n `backups and prevent runaway wal growth.`,\n ``,\n `Note that these checkpoints {italic can} be skipped if litestream is performing a`,\n `snapshot at the time (though snapshots are disabled by default). For such configurations,`,\n `the {bold ZERO_LITESTREAM_MAX_WAL_SIZE_MB} provides an emergency break to prevent`,\n `exceeding available disk space.`,\n ``,\n `Set this to 0 to disable and instead rely on the litestream's default {bold truncate-page-n}`,\n `emergency break.`,\n ``,\n `This feature is only enabled with {bold ZERO_LITESTREAM_BACKUP_USING_V5}.`,\n ],\n },\n\n maxWalSizeMB: {\n type: v.number().optional(() => 10240),\n desc: [\n `A fail-safe that pauses writes once the un-checkpointed WAL reaches this size,`,\n `resuming when litestream manages to checkpoint it. This bounds WAL growth (and`,\n `ultimately disk usage) whenever litestream cannot checkpoint — e.g. while it holds`,\n `the checkpoint lock for an in-progress snapshot — and serves as an alternative to`,\n `litestream's {bold truncate-page-n} emergency checkpoint, which would otherwise block`,\n `writes for a second \"bounary\" snapshot.`,\n ``,\n `Size this generously relative to available disk; it should rarely be hit, as`,\n `{bold ZERO_LITESTREAM_FORCE_CHECKPOINT_THRESHOLD_MB} keeps the WAL far smaller in`,\n `normal operation. Set to {bold 0} to disable.`,\n ``,\n `This feature is only enabled with {bold ZERO_LITESTREAM_BACKUP_USING_V5}.`,\n ],\n },\n\n incrementalBackupIntervalMinutes: {\n type: v.number().optional(() => 15),\n desc: [\n `The interval between incremental v3 backups of the replica. Shorter intervals`,\n `reduce the amount of change history that needs to be replayed when catching`,\n `up a new view-syncer, at the expense of increasing the number of files needed`,\n `to download for the initial litestream restore.`,\n ``,\n `This option only applies to litestream v3 backups and will be deprecated/removed`,\n `once the zero-cache is transitioned to litestream v5. For configuring v5 backup`,\n `frequency, use {bold ZERO_LITESTREAM_INCREMENTAL_BACKUP_INTERVAL_SECONDS}.`,\n ],\n },\n\n snapshotBackupIntervalHours: {\n type: v.number().optional(() => 12),\n desc: [\n `The interval between snapshot backups of the replica. Applies to both`,\n `litestream v3 and v5 backups.`,\n ``,\n `For v3, each snapshot makes a full copy of the database to a new litestream`,\n `generation. This improves restore time at the expense of bandwidth.`,\n `Applications with a large database and low write rate can increase this`,\n `interval to reduce network usage for backups (litestream defaults to 24 hours).`,\n ``,\n `For v5, continuous compaction already keeps restore times low, so snapshots`,\n `serve a different purpose: they keep every file a restore needs within about`,\n `one interval of age, so that lifecycle policies can clean up old backups.`,\n `v5 snapshots are built by compacting the existing backup files rather than`,\n `reading the replica, so they do not block WAL checkpoints.`,\n ],\n },\n\n incrementalBackupIntervalSeconds: {\n type: v.number().optional(() => 15),\n desc: [\n `The interval between incremental v5 backups of the replica. With litestream v5`,\n `the upstream change source is not ACKed until the corresponding changes have been`,\n `applied to the replica and backed up by litestream. As such, shorter intervals`,\n `incur a higher number of backup storage writes and files managed (e.g. in s3),`,\n `while longer intervals result requiring a larger buffer for changes upstream `,\n `(e.g. per-replication slot wal records). The default value of 15 seconds targets`,\n `an s3 API cost of ~$1/month (not counting storage costs).`,\n ``,\n `This option only applies to litestream v5 backups. For v3 backups, use`,\n `{bold ZERO_LITESTREAM_INCREMENTAL_BACKUP_INTERVAL_MINUTES}.`,\n ],\n },\n\n restoreParallelism: {\n type: v.number().optional(() => 48),\n desc: [\n `The number of WAL files to download in parallel when performing the`,\n `initial restore of the replica from the backup.`,\n ],\n },\n\n multipartConcurrency: {\n type: v.number().optional(),\n desc: [\n `The number of parts (of size {bold --litestream-multipart-size} bytes)`,\n `to upload or download in parallel when backing up or restoring the snapshot.`,\n `Leave this unset to use 48, reduced as needed to keep the parts within`,\n `a quarter of the memory available to the container.`,\n ],\n },\n\n multipartSize: {\n type: v.number().optional(() => 16 * 1024 * 1024),\n desc: [\n `The size of each part when uploading or downloading the snapshot with`,\n `{bold --multipart-concurrency}. Note that up to {bold concurrency * size}`,\n `bytes of memory are used when backing up or restoring the snapshot.`,\n ],\n },\n },\n\n storageDBTmpDir: {\n type: v.string().optional(),\n desc: [\n `tmp directory for IVM operator storage. Leave unset to use os.tmpdir()`,\n ],\n },\n\n initialSync: {\n tableCopyWorkers: {\n type: v.number().optional(() => 5),\n desc: [\n `The number of parallel workers used to copy tables during initial sync.`,\n `Each worker uses a database connection and will buffer up to (approximately)`,\n `10 MB of table data in memory during initial sync. Increasing the number of`,\n `workers may improve initial sync speed; however, note that local disk throughput`,\n `(i.e. IOPS), upstream CPU, and network bandwidth may also be bottlenecks.`,\n ],\n },\n\n profileCopy: {\n type: v.boolean().optional(),\n hidden: true,\n desc: [\n `Takes a cpu profile during the copy phase initial-sync, storing it as a JSON file`,\n `initial-copy.cpuprofile in the tmp directory.`,\n ],\n },\n\n textCopy: {\n type: v.boolean().optional(() => false),\n desc: [\n `Use text-format COPY instead of binary COPY for initial sync and`,\n `backfill streaming. This is slower but can work around issues with`,\n `binary encoding of certain data types.`,\n ],\n },\n },\n\n shadowSync: {\n enabled: {\n type: v.boolean().optional(() => false),\n desc: [\n `Periodically exercises the initial-sync code path against a sample of`,\n `rows from every published table, writing to a throwaway SQLite database.`,\n `This acts as a canary: if the real initial-sync path ever breaks (schema`,\n `drift, PG version quirks, etc.), the shadow run fails before a customer`,\n `actually needs a full reset.`,\n ],\n },\n\n intervalHours: {\n type: v.number().optional(() => 12),\n desc: [\n `The interval between shadow initial-sync runs, in hours. The first`,\n `run fires within [2/3, 1) of this interval after startup, so the`,\n `canary completes at least once per task lifetime (the replication`,\n `manager is restarted every ~24h) while still jittering so a fleet`,\n `restart does not cause all tasks to canary simultaneously.`,\n ],\n },\n\n sampleRate: {\n type: v.number().optional(() => 0.1),\n desc: [\n `The BERNOULLI sampling rate for each table (0 < rate <= 1). A value of`,\n `1 disables sampling and copies all rows (still subject to`,\n `{bold max-rows-per-table}).`,\n ],\n },\n\n maxRowsPerTable: {\n type: v.number().optional(() => 10000),\n desc: [\n `The hard upper bound on rows copied per table per shadow run. Guards`,\n `against unexpectedly large tables consuming disk / upstream bandwidth.`,\n ],\n },\n },\n\n /** @deprecated */\n targetClientRowCount: {\n type: v.number().optional(() => 20_000),\n deprecated: [\n 'This option is no longer used and will be removed in a future version.',\n 'The client-side cache no longer enforces a row limit. Instead, TTL-based expiration',\n 'automatically manages cache size to prevent unbounded growth.',\n ],\n hidden: true,\n },\n\n lazyStartup: {\n type: v.boolean().optional(() => false),\n desc: [\n 'Delay starting the majority of zero-cache until first request.',\n '',\n 'This is mainly intended to avoid connecting to Postgres replication stream',\n 'until the first request is received, which can be useful i.e., for preview instances.',\n '',\n 'Currently only supported in single-node mode.',\n ],\n },\n\n serverVersion: {\n type: v.string().optional(),\n desc: [`The version string outputted to logs when the server starts up.`],\n },\n\n enableTelemetry: {\n type: v.boolean().optional(() => true),\n desc: [\n `Set to false to opt out of telemetry collection.`,\n ``,\n `This helps us improve Zero by collecting anonymous usage data.`,\n `Setting the DO_NOT_TRACK environment variable also disables telemetry.`,\n ],\n },\n\n cloudEvent: {\n sinkEnv: {\n type: v.string().optional(),\n desc: [\n `ENV variable containing a URI to a CloudEvents sink. When set, ZeroEvents`,\n `will be published to the sink as the {bold data} field of CloudEvents.`,\n `The {bold source} field of the CloudEvents will be set to the {bold ZERO_TASK_ID},`,\n `along with any extension attributes specified by the {bold ZERO_CLOUD_EVENT_EXTENSION_OVERRIDES_ENV}.`,\n ``,\n `This configuration is modeled to easily integrate with a knative K_SINK binding,`,\n `(i.e. https://github.com/knative/eventing/blob/main/docs/spec/sources.md#sinkbinding).`,\n `However, any CloudEvents sink can be used.`,\n ],\n },\n\n extensionOverridesEnv: {\n type: v.string().optional(),\n desc: [\n `ENV variable containing a JSON stringified object with an {bold extensions} field`,\n `containing attributes that should be added or overridden on outbound CloudEvents.`,\n ``,\n `This configuration is modeled to easily integrate with a knative K_CE_OVERRIDES binding,`,\n `(i.e. https://github.com/knative/eventing/blob/main/docs/spec/sources.md#sinkbinding).`,\n ],\n },\n },\n};\n\nexport type ZeroConfig = Config<typeof zeroOptions>;\n\nlet loadedConfig: Config<typeof zeroOptions> | undefined;\n\nexport function getZeroConfig(\n opts: Omit<ParseOptions, 'envNamePrefix'> = {},\n): ZeroConfig {\n if (!loadedConfig || singleProcessMode()) {\n loadedConfig = parseOptions(zeroOptions, {\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n emitDeprecationWarnings: false, // overridden at the top level parse\n ...opts,\n });\n\n if (loadedConfig.queryHydrationStats) {\n runtimeDebugFlags.trackRowCountsVended = true;\n }\n }\n return loadedConfig;\n}\n\n/**\n * Parses only the log options, ignoring all other flags and environment\n * variables. For lightweight workers that need to set up logging but do not\n * need (or require) the rest of the zero config to be present or normalized.\n */\nexport function getLogConfig(\n opts: Omit<ParseOptions, 'envNamePrefix' | 'allowUnknown'> = {},\n): Pick<ZeroConfig, 'log'> {\n return parseOptions(\n {log: logOptions},\n {\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n emitDeprecationWarnings: false,\n allowUnknown: true,\n ...opts,\n },\n );\n}\n\n/**\n * Same as {@link getZeroConfig}, with an additional check that the\n * config has already been normalized (i.e. by the top level server/runner).\n */\nexport function getNormalizedZeroConfig(\n opts: Omit<ParseOptions, 'envNamePrefix'> = {},\n): NormalizedZeroConfig {\n const config = getZeroConfig(opts);\n assertNormalized(config);\n return config;\n}\n\n/**\n * Gets the server version from the config if provided. Otherwise it gets it\n * from the Zero package.json.\n */\nexport function getServerVersion(\n config: Pick<ZeroConfig, 'serverVersion'> | undefined,\n): string {\n return config?.serverVersion ?? packageJson.version;\n}\n\n/**\n * The access that a password grants to zero-cache's protected endpoints.\n * `admin` grants access to all of them. `operator` grants access only to the\n * ones that cannot expose application data (see `--operator-password`).\n */\nexport type AdminAccess = 'admin' | 'operator';\n\n/**\n * Returns whether `password` is the admin password. Endpoints that can expose\n * application data must use this, which never accepts the operator password.\n */\nexport function isAdminPasswordValid(\n lc: LogContext,\n config: Pick<NormalizedZeroConfig, 'adminPassword'>,\n password: string | undefined,\n): boolean {\n return getAccess(lc, config, undefined, password) === 'admin';\n}\n\n/**\n * Returns the access that `password` grants, accepting either the admin\n * password or the operator password, or `undefined` if it grants none.\n *\n * Only endpoints that cannot expose application data may use this, and they\n * must not serve anything to `operator` access that `--operator-password`\n * documents as withheld.\n */\nexport function getOperatorAccess(\n lc: LogContext,\n config: Pick<NormalizedZeroConfig, 'adminPassword' | 'operatorPassword'>,\n password: string | undefined,\n): AdminAccess | undefined {\n return getAccess(lc, config, config.operatorPassword, password);\n}\n\nfunction getAccess(\n lc: LogContext,\n {adminPassword}: Pick<NormalizedZeroConfig, 'adminPassword'>,\n operatorPassword: string | undefined,\n password: string | undefined,\n): AdminAccess | undefined {\n // If development mode, password is optional\n // We use process.env.NODE_ENV === 'development' as a sign that we're in\n // development mode, rather than a custom env var like ZERO_DEVELOPMENT_MODE,\n // because NODE_ENV is more standard and is already used by many tools.\n // Note that if NODE_ENV is not set, we assume production mode.\n\n if (!password && !adminPassword && isDevelopmentMode()) {\n warnOnce(\n lc,\n 'No admin password set; allowing access in development mode only',\n );\n return 'admin';\n }\n\n if (!adminPassword && !operatorPassword) {\n lc.warn?.('No admin password set; denying access');\n return undefined;\n }\n\n // Compare against both configured passwords (rather than stopping at the\n // first match) so that timing does not reveal which one matched.\n const isAdmin = passwordMatches(password, adminPassword);\n const isOperator = passwordMatches(password, operatorPassword);\n\n if (isAdmin) {\n lc.debug?.('Admin password accepted');\n return 'admin';\n }\n if (isOperator) {\n lc.debug?.('Operator password accepted');\n return 'operator';\n }\n lc.warn?.(\n operatorPassword\n ? 'Invalid admin or operator password'\n : 'Invalid admin password',\n );\n return undefined;\n}\n\nfunction passwordMatches(\n password: string | undefined,\n expected: string | undefined,\n): boolean {\n if (!expected) {\n return false;\n }\n\n // Use constant-time comparison to prevent timing attacks\n const passwordBuffer = Buffer.from(password ?? '');\n const expectedBuffer = Buffer.from(expected);\n\n // Handle length mismatch in constant time\n if (passwordBuffer.length !== expectedBuffer.length) {\n // Perform dummy comparison to maintain constant timing\n timingSafeEqual(expectedBuffer, expectedBuffer);\n return false;\n }\n\n return timingSafeEqual(passwordBuffer, expectedBuffer);\n}\n\nlet hasWarned = false;\n\nfunction warnOnce(lc: LogContext, msg: string) {\n if (!hasWarned) {\n lc.warn?.(msg);\n hasWarned = true;\n }\n}\n\n// For testing purposes - reset the warning state\nexport function resetWarnOnceState() {\n hasWarned = false;\n}\n"],"mappings":"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,MAAM,CAAC,8DAA8D;GACrE,QAAQ;EACV;EAEA,+BAA+B;GAC7B,MAAM,eAAE,OAAO,EAAE,eAAe,GAAI;GACpC,MAAM,CAAC,uDAAuD;GAC9D,QAAQ;EACV;EAEA,iCAAiC;GAC/B,MAAM,eAAE,OAAO,EAAE,eAAe,GAAO;GACvC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;GACF;GACA,QAAQ;EACV;EAEA,iCAAiC;GAC/B,MAAM,eAAE,OAAO,EAAE,eAAe,GAAI;GACpC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;EACF;EAEA,uCAAuC;GACrC,MAAM,eAAE,OAAO,EAAE,eAAe,CAAG;GACnC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;EACF;EAEA,6CAA6C;GAC3C,MAAM,eAAE,OAAO,EAAE,eAAe,EAAE;GAClC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;EACF;CACF;CAEA,QAAQ;EACN,MAAM,eAAE,OAAO,EAAE,SAAS;EAC1B,MAAM;GACJ;GACA;GACA;GACA;GACA;EACF;CACF;CAEA;CAEA,gBAAgB;EACd,MAAM,eAAE,OAAO,EAAE,SAAS;EAC1B,MAAM;GACJ;GACA;GACA;GACA;EACF;CACF;CAEA,WAAW;EACT,MAAM,eAAE,QAAQ,EAAE,eAAe,IAAI;EACrC,MAAM;GACJ;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;CACF;CAEA,gBAAgB;EACd,kBAAkB;GAChB,MAAM,eAAE,OAAO,EAAE,eAAe,GAAK;GACrC,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;EA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"}