gencow 0.1.228 → 0.1.229

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 (2) hide show
  1. package/package.json +3 -3
  2. package/runtime/server.mjs +487 -51
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.228",
3
+ "version": "0.1.229",
4
4
  "description": "Gencow — AI Backend Engine",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,9 +37,9 @@
37
37
  "ai": "^6.0.233",
38
38
  "@types/node": "^25.9.5",
39
39
  "better-auth": "^1.6.23",
40
- "@gencow/client": "0.2.7",
41
40
  "@gencow/core": "0.1.44",
42
- "@gencow/react": "0.2.7"
41
+ "@gencow/react": "0.2.7",
42
+ "@gencow/client": "0.2.7"
43
43
  },
44
44
  "scripts": {
45
45
  "prebuild": "pnpm --filter @gencow/migration-contract run build && pnpm --filter @gencow/server run build",
@@ -9927,6 +9927,14 @@ var init_deployment_executor_authority_contract = __esm({
9927
9927
  "enqueue_tenant_database_authority_request(integer,uuid,text,text,text,text,bigint,text)",
9928
9928
  ["EXECUTE"],
9929
9929
  { phase: "execute", enforcement: "exact" }
9930
+ ),
9931
+ // Topology rows remain owner-only. The executor can perform exactly
9932
+ // one atomic candidate gateway transition through this constrained
9933
+ // security-definer capability; it never receives table write grants.
9934
+ objectAuthority(
9935
+ "transition_app_serving_route_gateway_target(text,text,text,text,text,jsonb,boolean)",
9936
+ ["EXECUTE"],
9937
+ { phase: "execute", enforcement: "exact" }
9930
9938
  )
9931
9939
  ),
9932
9940
  closedWorld: { tables: true, sequences: true },
@@ -101904,6 +101912,164 @@ var init_server_serving_route_publication_bootstrap = __esm({
101904
101912
  )`,
101905
101913
  `CREATE UNIQUE INDEX IF NOT EXISTS app_serving_route_topologies_active_environment_unique
101906
101914
  ON app_serving_route_topologies (environment) WHERE state = 'active'`,
101915
+ `CREATE OR REPLACE FUNCTION public.transition_app_serving_route_gateway_target(
101916
+ requested_environment TEXT,
101917
+ requested_topology_revision TEXT,
101918
+ expected_active_revision TEXT,
101919
+ requested_projector_id TEXT,
101920
+ requested_topology_hash TEXT,
101921
+ requested_target_set_hashes JSONB,
101922
+ requested_remove BOOLEAN
101923
+ )
101924
+ RETURNS TABLE (
101925
+ topology_revision TEXT,
101926
+ previous_topology_revision TEXT,
101927
+ replayed BOOLEAN
101928
+ )
101929
+ LANGUAGE plpgsql
101930
+ SECURITY DEFINER
101931
+ SET search_path = pg_catalog, public
101932
+ AS $transition_app_serving_route_gateway_target$
101933
+ DECLARE
101934
+ active_revision TEXT;
101935
+ existing_state TEXT;
101936
+ existing_previous_revision TEXT;
101937
+ BEGIN
101938
+ -- This is deliberately a PROD emergency-candidate capability, not a
101939
+ -- generic topology writer. The fixed identity prevents an executor
101940
+ -- credential from retiring an incumbent edge/gateway projector.
101941
+ IF requested_environment <> 'prod'
101942
+ OR requested_topology_revision !~ '^prod-route-realtime(?:-rb)?-[a-f0-9]{12}$'
101943
+ OR expected_active_revision !~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
101944
+ OR requested_projector_id <> 'gateway-node-1-realtime-candidate'
101945
+ OR requested_topology_hash !~ '^[a-f0-9]{64}$'
101946
+ OR requested_target_set_hashes IS NULL
101947
+ OR jsonb_typeof(requested_target_set_hashes) <> 'object'
101948
+ OR requested_topology_revision = expected_active_revision THEN
101949
+ RAISE EXCEPTION 'APP_SERVING_ROUTE_TOPOLOGY_INVALID' USING ERRCODE = '22023';
101950
+ END IF;
101951
+
101952
+ PERFORM pg_advisory_xact_lock(hashtextextended('app-serving-route-topology:' || requested_environment, 0));
101953
+ SELECT topology.state, topology.previous_topology_revision
101954
+ INTO existing_state, existing_previous_revision
101955
+ FROM public.app_serving_route_topologies AS topology
101956
+ WHERE topology.topology_revision = requested_topology_revision
101957
+ FOR UPDATE;
101958
+ IF FOUND THEN
101959
+ IF existing_state = 'active'
101960
+ AND existing_previous_revision = expected_active_revision
101961
+ AND EXISTS (
101962
+ SELECT 1 FROM public.app_serving_route_topologies AS topology
101963
+ WHERE topology.topology_revision = requested_topology_revision
101964
+ AND topology.topology_hash = requested_topology_hash
101965
+ ) THEN
101966
+ RETURN QUERY SELECT requested_topology_revision, expected_active_revision, true;
101967
+ RETURN;
101968
+ END IF;
101969
+ RAISE EXCEPTION 'APP_SERVING_ROUTE_TOPOLOGY_CONFLICT' USING ERRCODE = '23505';
101970
+ END IF;
101971
+
101972
+ SELECT topology.topology_revision
101973
+ INTO active_revision
101974
+ FROM public.app_serving_route_topologies AS topology
101975
+ WHERE topology.environment = requested_environment AND topology.state = 'active'
101976
+ FOR UPDATE;
101977
+ IF active_revision IS NULL OR active_revision <> expected_active_revision THEN
101978
+ RAISE EXCEPTION 'APP_SERVING_ROUTE_TOPOLOGY_CAS_CONFLICT' USING ERRCODE = '40001';
101979
+ END IF;
101980
+
101981
+ IF NOT EXISTS (
101982
+ SELECT 1 FROM public.app_serving_route_target_sets AS target_set
101983
+ WHERE target_set.topology_revision = active_revision
101984
+ ) THEN
101985
+ RAISE EXCEPTION 'APP_SERVING_ROUTE_ACTIVE_TOPOLOGY_INVALID' USING ERRCODE = '23514';
101986
+ END IF;
101987
+ IF EXISTS (
101988
+ SELECT 1
101989
+ FROM public.app_serving_route_target_sets AS target_set
101990
+ LEFT JOIN LATERAL (
101991
+ SELECT requested_target_set_hashes ->> target_set.target_set_id AS target_set_hash
101992
+ ) AS supplied ON true
101993
+ WHERE target_set.topology_revision = active_revision
101994
+ AND (supplied.target_set_hash IS NULL OR supplied.target_set_hash !~ '^[a-f0-9]{64}$')
101995
+ ) OR EXISTS (
101996
+ SELECT 1
101997
+ FROM jsonb_object_keys(requested_target_set_hashes) AS supplied(target_set_id)
101998
+ WHERE NOT EXISTS (
101999
+ SELECT 1 FROM public.app_serving_route_target_sets AS target_set
102000
+ WHERE target_set.topology_revision = active_revision
102001
+ AND target_set.target_set_id = supplied.target_set_id
102002
+ )
102003
+ ) THEN
102004
+ RAISE EXCEPTION 'APP_SERVING_ROUTE_TOPOLOGY_HASH_SET_INVALID' USING ERRCODE = '22023';
102005
+ END IF;
102006
+ IF requested_remove AND NOT EXISTS (
102007
+ SELECT 1 FROM public.app_serving_route_topology_targets AS target
102008
+ WHERE target.topology_revision = active_revision AND target.projector_id = requested_projector_id
102009
+ ) THEN
102010
+ RAISE EXCEPTION 'APP_SERVING_ROUTE_TOPOLOGY_CAS_CONFLICT' USING ERRCODE = '40001';
102011
+ END IF;
102012
+ IF requested_remove AND EXISTS (
102013
+ SELECT 1
102014
+ FROM public.app_serving_route_target_sets AS target_set
102015
+ WHERE target_set.topology_revision = active_revision
102016
+ AND NOT EXISTS (
102017
+ SELECT 1 FROM public.app_serving_route_topology_targets AS target
102018
+ WHERE target.topology_revision = active_revision
102019
+ AND target.target_set_id = target_set.target_set_id
102020
+ AND target.projector_id <> requested_projector_id
102021
+ )
102022
+ ) THEN
102023
+ RAISE EXCEPTION 'APP_SERVING_ROUTE_TOPOLOGY_INVALID' USING ERRCODE = '22023';
102024
+ END IF;
102025
+
102026
+ INSERT INTO public.app_serving_route_topologies (
102027
+ topology_revision, environment, topology_hash, state, created_at, updated_at
102028
+ ) VALUES (
102029
+ requested_topology_revision, requested_environment, requested_topology_hash, 'staged', NOW(), NOW()
102030
+ );
102031
+ INSERT INTO public.app_serving_route_target_sets (
102032
+ topology_revision, target_set_id, purpose, target_set_hash, created_at
102033
+ )
102034
+ SELECT requested_topology_revision, target_set.target_set_id, target_set.purpose,
102035
+ requested_target_set_hashes ->> target_set.target_set_id, NOW()
102036
+ FROM public.app_serving_route_target_sets AS target_set
102037
+ WHERE target_set.topology_revision = active_revision;
102038
+ INSERT INTO public.app_serving_route_topology_targets (
102039
+ topology_revision, target_set_id, projector_id, target_kind, created_at
102040
+ )
102041
+ SELECT requested_topology_revision, target.target_set_id, target.projector_id, target.target_kind, NOW()
102042
+ FROM public.app_serving_route_topology_targets AS target
102043
+ WHERE target.topology_revision = active_revision
102044
+ AND (NOT requested_remove OR target.projector_id <> requested_projector_id)
102045
+ UNION ALL
102046
+ SELECT requested_topology_revision, target_set.target_set_id, requested_projector_id, 'gateway', NOW()
102047
+ FROM public.app_serving_route_target_sets AS target_set
102048
+ WHERE target_set.topology_revision = active_revision
102049
+ AND NOT requested_remove
102050
+ AND NOT EXISTS (
102051
+ SELECT 1 FROM public.app_serving_route_topology_targets AS target
102052
+ WHERE target.topology_revision = active_revision
102053
+ AND target.target_set_id = target_set.target_set_id
102054
+ AND target.projector_id = requested_projector_id
102055
+ );
102056
+
102057
+ UPDATE public.app_serving_route_topologies AS topology
102058
+ SET state = 'retired', retired_at = NOW(), updated_at = NOW()
102059
+ WHERE topology.topology_revision = active_revision AND topology.state = 'active';
102060
+ IF NOT FOUND THEN
102061
+ RAISE EXCEPTION 'APP_SERVING_ROUTE_TOPOLOGY_CAS_CONFLICT' USING ERRCODE = '40001';
102062
+ END IF;
102063
+ UPDATE public.app_serving_route_topologies AS topology
102064
+ SET state = 'active', previous_topology_revision = active_revision,
102065
+ activated_at = NOW(), updated_at = NOW()
102066
+ WHERE topology.topology_revision = requested_topology_revision AND topology.state = 'staged';
102067
+ IF NOT FOUND THEN
102068
+ RAISE EXCEPTION 'APP_SERVING_ROUTE_TOPOLOGY_CAS_CONFLICT' USING ERRCODE = '40001';
102069
+ END IF;
102070
+ RETURN QUERY SELECT requested_topology_revision, active_revision, false;
102071
+ END
102072
+ $transition_app_serving_route_gateway_target$`,
101907
102073
  `CREATE TABLE IF NOT EXISTS app_serving_route_target_sets (
101908
102074
  topology_revision TEXT NOT NULL,
101909
102075
  target_set_id TEXT NOT NULL,
@@ -102279,6 +102445,7 @@ var init_server_serving_route_publication_bootstrap = __esm({
102279
102445
  `REVOKE ALL ON TABLE app_serving_route_topologies FROM PUBLIC`,
102280
102446
  `REVOKE ALL ON TABLE app_serving_route_target_sets FROM PUBLIC`,
102281
102447
  `REVOKE ALL ON TABLE app_serving_route_topology_targets FROM PUBLIC`,
102448
+ `REVOKE ALL ON FUNCTION public.transition_app_serving_route_gateway_target(TEXT, TEXT, TEXT, TEXT, TEXT, JSONB, BOOLEAN) FROM PUBLIC`,
102282
102449
  `DO $app_serving_route_roles$
102283
102450
  DECLARE runtime_role TEXT;
102284
102451
  BEGIN
@@ -103527,6 +103694,7 @@ async function ensurePlatformSchemaUpgrade(params) {
103527
103694
  if (!params.isPlatform)
103528
103695
  return;
103529
103696
  const logger3 = params.logger ?? console;
103697
+ await params.rawSql(`CREATE EXTENSION IF NOT EXISTS pg_trgm`);
103530
103698
  await ensurePlatformNodeSchema({ rawSql: params.rawSql });
103531
103699
  try {
103532
103700
  await params.rawSql(`ALTER TABLE apps ADD COLUMN IF NOT EXISTS display_name TEXT`);
@@ -111712,6 +111880,63 @@ function notifyQueryInvalidate(params) {
111712
111880
  params.onMessageSent?.(sent, sentPayloadBytes);
111713
111881
  return sent;
111714
111882
  }
111883
+ function notifyAuthorizedQueryInvalidateByLegacyKeys(params) {
111884
+ const appSubs = authorizedQuerySubscriptions.get(params.appName);
111885
+ if (!appSubs) {
111886
+ params.metrics.noSubscribers++;
111887
+ return 0;
111888
+ }
111889
+ const targets = /* @__PURE__ */ new Map();
111890
+ for (const [subscriptionKey, clients] of appSubs) {
111891
+ const legacyQueries = params.queryKeys.map((queryKey) => queryKey.split("::", 1)[0]);
111892
+ if (!params.queryKeys.some((queryKey) => subscriptionKeyMatchesQueryKey(subscriptionKey, queryKey)) && !legacyQueries.some((query2) => [...clients.values()].some((auth) => auth.query === query2))) continue;
111893
+ for (const [ws2, auth] of clients) {
111894
+ if (auth.expiresAt <= Date.now()) {
111895
+ clients.delete(ws2);
111896
+ params.metrics.staleQuerySubscriptions++;
111897
+ continue;
111898
+ }
111899
+ const set2 = targets.get(ws2) ?? /* @__PURE__ */ new Set();
111900
+ set2.add(auth);
111901
+ targets.set(ws2, set2);
111902
+ }
111903
+ }
111904
+ if (targets.size === 0) {
111905
+ params.metrics.noSubscribers++;
111906
+ return 0;
111907
+ }
111908
+ let sent = 0;
111909
+ let sentPayloadBytes = 0;
111910
+ for (const [ws2, auths] of targets) {
111911
+ for (const auth of auths) {
111912
+ const message = JSON.stringify({
111913
+ type: "query:invalidate",
111914
+ query: auth.query,
111915
+ subscriptionKey: auth.subscriptionKey,
111916
+ eventId: `legacy_${Date.now().toString(36)}`
111917
+ });
111918
+ const payloadBytes = Buffer.byteLength(message);
111919
+ params.metrics.queryInvalidations++;
111920
+ params.metrics.payloadBytes += payloadBytes;
111921
+ if (payloadBytes > params.limits.maxPayloadBytes) {
111922
+ params.metrics.payloadDrops++;
111923
+ continue;
111924
+ }
111925
+ try {
111926
+ ws2.send(message);
111927
+ sent++;
111928
+ sentPayloadBytes += payloadBytes;
111929
+ } catch {
111930
+ params.metrics.sendErrors++;
111931
+ params.metrics.droppedConnections++;
111932
+ params.onSocketFailure(ws2);
111933
+ }
111934
+ }
111935
+ }
111936
+ params.metrics.sent += sent;
111937
+ params.onMessageSent?.(sent, sentPayloadBytes);
111938
+ return sent;
111939
+ }
111715
111940
  function notifyQueryRevoke(params) {
111716
111941
  const appSubs = authorizedQuerySubscriptions.get(params.appName);
111717
111942
  const clients = appSubs?.get(params.subscriptionKey);
@@ -149123,18 +149348,20 @@ function notifyEmit(appName, queryKey, data) {
149123
149348
  recordRealtimeMessageDelivery(appName, sent, sent * payloadBytes);
149124
149349
  return sent;
149125
149350
  }
149126
- function notifyInvalidate(appName, queryKeys) {
149351
+ function notifyInvalidate(appName, queryKeys, bridgeScoped = true) {
149127
149352
  const appSubs = subscriptions.get(appName);
149128
- if (!appSubs) {
149129
- metrics2.noSubscribers++;
149130
- return 0;
149131
- }
149353
+ const scopedSent = bridgeScoped ? notifyAuthorizedQueryInvalidateByLegacyKeys({
149354
+ appName,
149355
+ queryKeys,
149356
+ limits: gatewayLimits,
149357
+ metrics: metrics2,
149358
+ onMessageSent: (messageCount, payloadBytes) => recordRealtimeMessageDelivery(appName, messageCount, payloadBytes),
149359
+ onSocketFailure: handleClose
149360
+ }) : 0;
149361
+ if (!appSubs) return scopedSent;
149132
149362
  const targets = /* @__PURE__ */ new Map();
149133
149363
  collectLegacyInvalidateTargets(appSubs, queryKeys, targets);
149134
- if (targets.size === 0) {
149135
- metrics2.noSubscribers++;
149136
- return 0;
149137
- }
149364
+ if (targets.size === 0) return scopedSent;
149138
149365
  let sent = 0;
149139
149366
  let sentPayloadBytes = 0;
149140
149367
  for (const [ws2, keys2] of targets) {
@@ -149158,12 +149385,12 @@ function notifyInvalidate(appName, queryKeys) {
149158
149385
  }
149159
149386
  metrics2.sent += sent;
149160
149387
  recordRealtimeMessageDelivery(appName, sent, sentPayloadBytes);
149161
- return sent;
149388
+ return sent + scopedSent;
149162
149389
  }
149163
149390
  function notifyQueryInvalidate2(appName, query2, subscriptionKey, eventId = `evt_${Date.now().toString(36)}`, scopeHash = "", legacyQueryKey, crudRealtimeEmitMode = "dual") {
149164
149391
  countGeneratedCrudEmitModeMetrics(metrics2, crudRealtimeEmitMode, legacyQueryKey !== void 0);
149165
149392
  const emitPlan = getGeneratedCrudEmitPlan({ mode: crudRealtimeEmitMode, legacyQueryKey });
149166
- const legacySent = emitPlan.sendLegacy && legacyQueryKey ? notifyInvalidate(appName, [legacyQueryKey]) : 0;
149393
+ const legacySent = emitPlan.sendLegacy && legacyQueryKey ? notifyInvalidate(appName, [legacyQueryKey], false) : 0;
149167
149394
  const scopedSent = emitPlan.sendScoped ? notifyQueryInvalidate({
149168
149395
  appName,
149169
149396
  query: query2,
@@ -167055,6 +167282,31 @@ var init_server_platform_runtime_helpers = __esm({
167055
167282
  }
167056
167283
  });
167057
167284
 
167285
+ // ../server/dist/server-platform-realtime-forwarder.js
167286
+ async function forwardPlatformRealtimeNotify(params) {
167287
+ if (process.env.IS_PLATFORM !== "true")
167288
+ return null;
167289
+ const url2 = process.env.GENCOW_REALTIME_GATEWAY_NOTIFY_URL?.trim() || "http://127.0.0.1:4522/internal/realtime-notify";
167290
+ try {
167291
+ const response = await fetch(url2, {
167292
+ method: "POST",
167293
+ headers: { "Content-Type": "application/json", "X-Internal-Token": params.token },
167294
+ body: JSON.stringify({ appName: params.appName, ...params.body }),
167295
+ signal: AbortSignal.timeout(2e3)
167296
+ });
167297
+ if (response.status !== 401 && response.status !== 403)
167298
+ return response;
167299
+ } catch (error51) {
167300
+ params.logger?.warn("[realtime] Route Gateway forward unavailable; using local compatibility path", error51);
167301
+ }
167302
+ return null;
167303
+ }
167304
+ var init_server_platform_realtime_forwarder = __esm({
167305
+ "../server/dist/server-platform-realtime-forwarder.js"() {
167306
+ "use strict";
167307
+ }
167308
+ });
167309
+
167058
167310
  // ../server/dist/server-platform-analytics-ingest.js
167059
167311
  import { lstatSync, readFileSync as readFileSync18 } from "node:fs";
167060
167312
  import { isAbsolute as isAbsolute9, resolve as resolve46 } from "node:path";
@@ -185980,6 +186232,96 @@ function rowsFromResult29(result2) {
185980
186232
  function hashCanonical(value) {
185981
186233
  return createHash37("sha256").update(JSON.stringify(value)).digest("hex");
185982
186234
  }
186235
+ function normalizeTopology(input) {
186236
+ if (!ENVIRONMENTS.has(input.environment) || !REFERENCE2.test(input.topologyRevision) || input.targetSets.length < 1 || input.targetSets.length > MAX_TARGET_SETS) {
186237
+ fail10("APP_SERVING_ROUTE_TOPOLOGY_INVALID");
186238
+ }
186239
+ const targetSets = input.targetSets.map((set2) => {
186240
+ const targets = [...set2.targets].sort(
186241
+ (left, right) => left.projectorId < right.projectorId ? -1 : left.projectorId > right.projectorId ? 1 : 0
186242
+ );
186243
+ if (!REFERENCE2.test(set2.targetSetId) || set2.purpose !== "upsert" && set2.purpose !== "tombstone" || targets.length < 1 || targets.length > MAX_TARGETS_PER_SET || targets.some(
186244
+ (target) => !REFERENCE2.test(target.projectorId) || !TARGET_KINDS.has(target.targetKind)
186245
+ ) || new Set(targets.map((target) => target.projectorId)).size !== targets.length) {
186246
+ fail10("APP_SERVING_ROUTE_TOPOLOGY_INVALID");
186247
+ }
186248
+ return {
186249
+ targetSetId: set2.targetSetId,
186250
+ purpose: set2.purpose,
186251
+ targets,
186252
+ targetSetHash: hashCanonical([set2.purpose, targets])
186253
+ };
186254
+ }).sort(
186255
+ (left, right) => left.targetSetId < right.targetSetId ? -1 : left.targetSetId > right.targetSetId ? 1 : 0
186256
+ );
186257
+ if (new Set(targetSets.map((set2) => set2.targetSetId)).size !== targetSets.length) {
186258
+ fail10("APP_SERVING_ROUTE_TOPOLOGY_INVALID");
186259
+ }
186260
+ const topologyHash = hashCanonical([
186261
+ 1,
186262
+ input.environment,
186263
+ input.topologyRevision,
186264
+ targetSets.map(({ targetSetHash: _hash2, ...set2 }) => set2)
186265
+ ]);
186266
+ return {
186267
+ environment: input.environment,
186268
+ topologyRevision: input.topologyRevision,
186269
+ targetSets,
186270
+ topologyHash,
186271
+ targetCount: targetSets.reduce((count3, set2) => count3 + set2.targets.length, 0)
186272
+ };
186273
+ }
186274
+ function definitionFromRows(rows4) {
186275
+ if (rows4.length === 0) return null;
186276
+ const first2 = rows4[0];
186277
+ const grouped = /* @__PURE__ */ new Map();
186278
+ for (const row of rows4) {
186279
+ const set2 = grouped.get(row.target_set_id) ?? {
186280
+ targetSetId: row.target_set_id,
186281
+ purpose: row.purpose,
186282
+ targets: []
186283
+ };
186284
+ set2.targets.push({
186285
+ projectorId: row.projector_id,
186286
+ targetKind: row.target_kind
186287
+ });
186288
+ grouped.set(row.target_set_id, set2);
186289
+ }
186290
+ return normalizeTopology({
186291
+ environment: first2.environment,
186292
+ topologyRevision: first2.topology_revision,
186293
+ targetSets: [...grouped.values()]
186294
+ });
186295
+ }
186296
+ async function readActiveAppServingRouteTopology(input) {
186297
+ if (!ENVIRONMENTS.has(input.environment)) fail10("APP_SERVING_ROUTE_TOPOLOGY_INVALID");
186298
+ const result2 = await input.db.execute(sql65`
186299
+ SELECT topology.environment, topology.topology_revision, topology.topology_hash,
186300
+ topology.state, topology.previous_topology_revision,
186301
+ target_set.target_set_id, target_set.purpose, target_set.target_set_hash,
186302
+ target.projector_id, target.target_kind
186303
+ FROM app_serving_route_topologies topology
186304
+ JOIN app_serving_route_target_sets target_set
186305
+ ON target_set.topology_revision = topology.topology_revision
186306
+ JOIN app_serving_route_topology_targets target
186307
+ ON target.topology_revision = target_set.topology_revision
186308
+ AND target.target_set_id = target_set.target_set_id
186309
+ WHERE topology.environment = ${input.environment}
186310
+ AND topology.state = 'active'
186311
+ ORDER BY target_set.target_set_id, target.projector_id
186312
+ `);
186313
+ const normalized = definitionFromRows(rowsFromResult29(result2));
186314
+ if (!normalized) return null;
186315
+ if (normalized.environment !== input.environment) fail10("APP_SERVING_ROUTE_TOPOLOGY_INVALID");
186316
+ return {
186317
+ topologyRevision: normalized.topologyRevision,
186318
+ targetSets: normalized.targetSets.map(({ targetSetId, purpose, targets }) => ({
186319
+ targetSetId,
186320
+ purpose,
186321
+ targets
186322
+ }))
186323
+ };
186324
+ }
185983
186325
  async function resolveAppServingRouteTargetSet(input) {
185984
186326
  if (!ENVIRONMENTS.has(input.environment) || !REFERENCE2.test(input.topologyRevision) || !REFERENCE2.test(input.targetSetId)) {
185985
186327
  fail10("APP_SERVING_ROUTE_TOPOLOGY_INVALID");
@@ -186008,12 +186350,21 @@ async function resolveAppServingRouteTargetSet(input) {
186008
186350
  }
186009
186351
  return targets;
186010
186352
  }
186011
- var REFERENCE2, ENVIRONMENTS;
186353
+ var REFERENCE2, ENVIRONMENTS, TARGET_KINDS, MAX_TARGET_SETS, MAX_TARGETS_PER_SET;
186012
186354
  var init_app_serving_route_topology_store = __esm({
186013
186355
  "../platform/src/app-serving-route-topology-store.ts"() {
186014
186356
  "use strict";
186015
186357
  REFERENCE2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
186016
186358
  ENVIRONMENTS = /* @__PURE__ */ new Set(["local", "dev", "qc", "prod"]);
186359
+ TARGET_KINDS = /* @__PURE__ */ new Set([
186360
+ "edge",
186361
+ "gateway",
186362
+ "static_origin",
186363
+ "analytics_collector",
186364
+ "domain_authorizer"
186365
+ ]);
186366
+ MAX_TARGET_SETS = 64;
186367
+ MAX_TARGETS_PER_SET = 64;
186017
186368
  }
186018
186369
  });
186019
186370
 
@@ -186111,6 +186462,43 @@ function rowsFromResult31(result2) {
186111
186462
  if (Array.isArray(result2)) return result2;
186112
186463
  return result2?.rows ?? [];
186113
186464
  }
186465
+ async function resolveAppServingRoutePreparationBindingInTransaction(input) {
186466
+ await input.acquireLock(input.tx, `app-serving-route-topology:${input.environment}`);
186467
+ const existingResult = await input.tx.execute(sql67`
186468
+ SELECT environment, topology_revision, target_set_id
186469
+ FROM app_serving_route_outbox
186470
+ WHERE app_id = ${input.appId}
186471
+ AND app_instance_id = ${input.appInstanceId}
186472
+ AND mutation_kind = ${input.mutationKind}
186473
+ AND source_revision = ${input.sourceRevision}
186474
+ AND phase = 'prepare'
186475
+ `);
186476
+ const existing = rowsFromResult31(existingResult);
186477
+ if (existing.length > 1 || existing[0] && existing[0].environment !== input.environment) {
186478
+ fail12("APP_SERVING_ROUTE_SOURCE_DECISION_CONFLICT");
186479
+ }
186480
+ if (existing[0]) {
186481
+ return {
186482
+ topologyRevision: existing[0].topology_revision,
186483
+ targetSetId: existing[0].target_set_id
186484
+ };
186485
+ }
186486
+ if (input.phase === "commit") {
186487
+ return { topologyRevision: input.topologyRevision, targetSetId: input.targetSetId };
186488
+ }
186489
+ const active = await readActiveAppServingRouteTopology({
186490
+ db: input.tx,
186491
+ environment: input.environment
186492
+ });
186493
+ const upsertTargetSets = active?.targetSets.filter((targetSet) => targetSet.purpose === "upsert") ?? [];
186494
+ if (!active || upsertTargetSets.length !== 1) {
186495
+ fail12("APP_SERVING_ROUTE_TOPOLOGY_TARGET_SET_UNAVAILABLE");
186496
+ }
186497
+ return {
186498
+ topologyRevision: active.topologyRevision,
186499
+ targetSetId: upsertTargetSets[0].targetSetId
186500
+ };
186501
+ }
186114
186502
  function normalizeInput(input) {
186115
186503
  const phaseValid = input.phase === "prepare" || input.phase === "commit" || input.phase === "tombstone";
186116
186504
  const dispositionValid = input.disposition === "upsert" || input.disposition === "tombstone";
@@ -186323,7 +186711,7 @@ async function commitAppServingRouteDecisionInTransaction(rawInput) {
186323
186711
  const acquireLock = customAcquireLock ?? ((executor, key) => executor.execute(sql67`SELECT pg_advisory_xact_lock(hashtextextended(${key}::text, 0))`));
186324
186712
  return commitNormalizedDecision(tx, input, acquireLock);
186325
186713
  }
186326
- async function inspectPreparedReplay(tx, input, current, requiredTargets) {
186714
+ async function inspectPreparedReplay(tx, input, current) {
186327
186715
  const routeEpoch = input.expectedRouteEpoch + 1;
186328
186716
  const predecessorHash = current?.entry_hash ?? null;
186329
186717
  const eventId = routeEventId({ ...input, routeEpoch, predecessorHash });
@@ -186347,6 +186735,14 @@ async function inspectPreparedReplay(tx, input, current, requiredTargets) {
186347
186735
  `);
186348
186736
  const row = rowsFromResult31(event)[0];
186349
186737
  if (!row) return null;
186738
+ const requiredTargets = await resolveAppServingRouteTargetSet({
186739
+ db: tx,
186740
+ environment: input.environment,
186741
+ topologyRevision: input.topologyRevision,
186742
+ targetSetId: input.targetSetId,
186743
+ purpose: "upsert",
186744
+ allowRetired: true
186745
+ });
186350
186746
  await assertReplayTargets(tx, eventId, "prepare", requiredTargets);
186351
186747
  return outcome(input, routeEpoch, predecessorHash, eventId, Number(row.publication_sequence), true);
186352
186748
  }
@@ -186425,43 +186821,69 @@ async function assertCommitPreparedAuthorityEpoch(tx, current, input) {
186425
186821
  }
186426
186822
  async function prepareNormalizedDecision(tx, input, acquireLock) {
186427
186823
  if (input.phase !== "prepare") fail12("APP_SERVING_ROUTE_DECISION_INVALID");
186428
- await acquireLock(tx, `app-serving-route:${input.appId}`);
186429
- const current = await loadAuthority(tx, input.appId);
186430
- const requiredTargets = await resolveAppServingRouteTargetSet({
186431
- db: tx,
186824
+ const binding = await resolveAppServingRoutePreparationBindingInTransaction({
186825
+ tx,
186432
186826
  environment: input.environment,
186827
+ appId: input.appId,
186828
+ appInstanceId: input.appInstanceId,
186829
+ phase: input.phase,
186830
+ mutationKind: input.mutationKind,
186831
+ sourceRevision: input.sourceRevision,
186433
186832
  topologyRevision: input.topologyRevision,
186434
186833
  targetSetId: input.targetSetId,
186435
- purpose: "upsert"
186834
+ acquireLock
186436
186835
  });
186437
- const replay = await inspectPreparedReplay(tx, input, current, requiredTargets);
186836
+ const boundInput = { ...input, ...binding };
186837
+ await acquireLock(tx, `app-serving-route:${boundInput.appId}`);
186838
+ const current = await loadAuthority(tx, boundInput.appId);
186839
+ const replay = await inspectPreparedReplay(tx, boundInput, current);
186438
186840
  if (replay) return replay;
186439
- await assertPrepareAuthorityEpoch(tx, current, input);
186440
- return persistPreparedDecision(tx, input, current, requiredTargets);
186841
+ const requiredTargets = await resolveAppServingRouteTargetSet({
186842
+ db: tx,
186843
+ environment: boundInput.environment,
186844
+ topologyRevision: boundInput.topologyRevision,
186845
+ targetSetId: boundInput.targetSetId,
186846
+ purpose: "upsert"
186847
+ });
186848
+ await assertPrepareAuthorityEpoch(tx, current, boundInput);
186849
+ return persistPreparedDecision(tx, boundInput, current, requiredTargets);
186441
186850
  }
186442
186851
  async function commitPreparedNormalizedDecision(tx, input, acquireLock) {
186443
186852
  if (input.phase !== "commit") fail12("APP_SERVING_ROUTE_DECISION_INVALID");
186444
- await acquireLock(tx, `app-serving-route:${input.appId}`);
186445
- const current = await loadAuthority(tx, input.appId);
186446
- await assertCommitPreparedAuthorityEpoch(tx, current, input);
186447
- const preparedInput = { ...input, phase: "prepare" };
186448
- const requiredTargets = await resolveAppServingRouteTargetSet({
186449
- db: tx,
186853
+ const binding = await resolveAppServingRoutePreparationBindingInTransaction({
186854
+ tx,
186450
186855
  environment: input.environment,
186856
+ appId: input.appId,
186857
+ appInstanceId: input.appInstanceId,
186858
+ phase: input.phase,
186859
+ mutationKind: input.mutationKind,
186860
+ sourceRevision: input.sourceRevision,
186451
186861
  topologyRevision: input.topologyRevision,
186452
186862
  targetSetId: input.targetSetId,
186863
+ acquireLock
186864
+ });
186865
+ const boundInput = { ...input, ...binding };
186866
+ await acquireLock(tx, `app-serving-route:${boundInput.appId}`);
186867
+ const current = await loadAuthority(tx, boundInput.appId);
186868
+ await assertCommitPreparedAuthorityEpoch(tx, current, boundInput);
186869
+ const preparedInput = { ...boundInput, phase: "prepare" };
186870
+ const requiredTargets = await resolveAppServingRouteTargetSet({
186871
+ db: tx,
186872
+ environment: boundInput.environment,
186873
+ topologyRevision: boundInput.topologyRevision,
186874
+ targetSetId: boundInput.targetSetId,
186453
186875
  purpose: "upsert",
186454
186876
  allowRetired: true
186455
186877
  });
186456
- const prepared = await inspectPreparedReplay(tx, preparedInput, current, requiredTargets);
186878
+ const prepared = await inspectPreparedReplay(tx, preparedInput, current);
186457
186879
  if (!prepared) fail12("APP_SERVING_ROUTE_PREPARE_REQUIRED");
186458
186880
  const convergence = await assessAppServingRouteConvergence({
186459
186881
  db: tx,
186460
186882
  eventId: prepared.eventId,
186461
- appId: input.appId
186883
+ appId: boundInput.appId
186462
186884
  });
186463
186885
  if (convergence.status !== "converged") fail12("APP_SERVING_ROUTE_PREPARE_NOT_CONVERGED");
186464
- return persistDecision(tx, input, current, requiredTargets);
186886
+ return persistDecision(tx, boundInput, current, requiredTargets);
186465
186887
  }
186466
186888
  function resolveDecisionLock(customAcquireLock) {
186467
186889
  return customAcquireLock ?? ((tx, key) => tx.execute(sql67`SELECT pg_advisory_xact_lock(hashtextextended(${key}::text, 0))`));
@@ -416540,6 +416962,18 @@ function replayOutcome(row) {
416540
416962
  }
416541
416963
  async function commitAppServingRouteSourceInTransaction(input) {
416542
416964
  const acquireLock = input.acquireLock ?? ((tx, key) => tx.execute(sql83`SELECT pg_advisory_xact_lock(hashtextextended(${key}::text, 0))`));
416965
+ const binding = input.phase === "tombstone" ? { topologyRevision: input.topologyRevision, targetSetId: input.targetSetId } : await resolveAppServingRoutePreparationBindingInTransaction({
416966
+ tx: input.tx,
416967
+ environment: input.environment,
416968
+ appId: input.source.appId,
416969
+ appInstanceId: input.source.appInstanceId,
416970
+ phase: input.phase,
416971
+ mutationKind: input.mutationKind,
416972
+ sourceRevision: input.sourceRevision,
416973
+ topologyRevision: input.topologyRevision,
416974
+ targetSetId: input.targetSetId,
416975
+ acquireLock
416976
+ });
416543
416977
  await acquireLock(input.tx, `app-serving-route:${input.source.appId}`);
416544
416978
  const replayResult = await input.tx.execute(sql83`
416545
416979
  SELECT event_id, publication_sequence, environment, app_id, app_instance_id, route_epoch,
@@ -416558,7 +416992,7 @@ async function commitAppServingRouteSourceInTransaction(input) {
416558
416992
  const replayEntryHash = Number.isSafeInteger(replayEpoch) ? hashServingRouteManifestEntry(
416559
416993
  compileAppServingRouteEntry({ ...input.source, routeEpoch: replayEpoch })
416560
416994
  ) : "";
416561
- if (replay.environment !== input.environment || replay.phase !== input.phase || replay.disposition !== input.source.disposition || replay.topology_revision !== input.topologyRevision || replay.target_set_id !== input.targetSetId || replay.entry_hash !== replayEntryHash) {
416995
+ if (replay.environment !== input.environment || replay.phase !== input.phase || replay.disposition !== input.source.disposition || replay.topology_revision !== binding.topologyRevision || replay.target_set_id !== binding.targetSetId || replay.entry_hash !== replayEntryHash) {
416562
416996
  fail15("APP_SERVING_ROUTE_SOURCE_DECISION_CONFLICT");
416563
416997
  }
416564
416998
  return replayOutcome(replay);
@@ -416602,7 +417036,7 @@ async function commitAppServingRouteSourceInTransaction(input) {
416602
417036
  const preparedEntryHash = Number.isSafeInteger(preparedEpoch) ? hashServingRouteManifestEntry(
416603
417037
  compileAppServingRouteEntry({ ...input.source, routeEpoch: preparedEpoch })
416604
417038
  ) : "";
416605
- if (!prepared || prepared.environment !== input.environment || prepared.disposition !== input.source.disposition || prepared.topology_revision !== input.topologyRevision || prepared.target_set_id !== input.targetSetId || prepared.entry_hash !== preparedEntryHash || preparedEpoch < 1) {
417039
+ if (!prepared || prepared.environment !== input.environment || prepared.disposition !== input.source.disposition || prepared.topology_revision !== binding.topologyRevision || prepared.target_set_id !== binding.targetSetId || prepared.entry_hash !== preparedEntryHash || preparedEpoch < 1) {
416606
417040
  fail15("APP_SERVING_ROUTE_SOURCE_DECISION_CONFLICT");
416607
417041
  }
416608
417042
  expectedRouteEpoch = preparedEpoch - 1;
@@ -416624,8 +417058,8 @@ async function commitAppServingRouteSourceInTransaction(input) {
416624
417058
  disposition: input.source.disposition,
416625
417059
  mutationKind: input.mutationKind,
416626
417060
  entry,
416627
- topologyRevision: input.topologyRevision,
416628
- targetSetId: input.targetSetId,
417061
+ topologyRevision: binding.topologyRevision,
417062
+ targetSetId: binding.targetSetId,
416629
417063
  sourceRevision: input.sourceRevision,
416630
417064
  acquireLock: async () => void 0
416631
417065
  };
@@ -432960,6 +433394,16 @@ function registerRealtimeNotifyRoute(params) {
432960
433394
  if (rateLimit2 && !rateLimit2.ok) {
432961
433395
  return c.json({ error: "Realtime notify rate limit exceeded", retryAfterMs: rateLimit2.retryAfterMs }, 429);
432962
433396
  }
433397
+ const forwarded = await forwardPlatformRealtimeNotify({
433398
+ appName: auth.appName,
433399
+ body,
433400
+ token: c.req.header("X-Internal-Token") || "",
433401
+ logger: logger3
433402
+ });
433403
+ if (forwarded) {
433404
+ const forwardedBody = await forwarded.json().catch(() => ({ error: "Realtime gateway unavailable" }));
433405
+ return c.json(forwardedBody, forwarded.status);
433406
+ }
432963
433407
  if (body.type === "emit") {
432964
433408
  if (typeof body.queryKey !== "string" || body.queryKey.length === 0) {
432965
433409
  return c.json({ error: "queryKey required" }, 400);
@@ -433514,6 +433958,7 @@ var init_server_platform_runtime_bootstrap = __esm({
433514
433958
  init_server_platform_account_deletion_finalizer_runtime();
433515
433959
  init_server_platform_runtime_helpers();
433516
433960
  init_server_platform_internal_middleware();
433961
+ init_server_platform_realtime_forwarder();
433517
433962
  init_server_platform_analytics_ingest();
433518
433963
  init_server_legacy_runtime_recovery_route();
433519
433964
  init_server_runtime_route_projection_runtime();
@@ -436256,10 +436701,6 @@ var HISTORICAL_INDEX_IDENTITIES = /* @__PURE__ */ new Map([
436256
436701
  ["app_delete_recover_terminal_replay", { legacyIndex: "0072", tagIndex: "0077", legacyIndexAliases: ["0069"] }],
436257
436702
  ["source_static_backup_split", { legacyIndex: "0073", tagIndex: "0078", legacyIndexAliases: ["0070"] }]
436258
436703
  ]);
436259
- var ROOT_HISTORICAL_RECEIPTS = /* @__PURE__ */ new Map([
436260
- ["0079_serving_route_recovery_capability", { timestampMillis: 1787565607145, createdAt: 1787565607e3 }],
436261
- ["0080_analytics_collector_route_target", { timestampMillis: 1787565608146, createdAt: 1787565608e3 }]
436262
- ]);
436263
436704
  var CANONICAL_HISTORICAL_RECEIPTS = /* @__PURE__ */ new Map([
436264
436705
  ["20260408_add_memory_metering", { timestampMillis: 17756064e5, createdAt: 17756064e5 }],
436265
436706
  ["20260825_add_analytics_ingest_event_id", { timestampMillis: 1787616000099, createdAt: 1787616e6 }],
@@ -436334,7 +436775,6 @@ function parseJournalIdentity(name, createdAt) {
436334
436775
  const rootLegacyCandidate = indexedMatch ? void 0 : ROOT_LEGACY_JOURNAL_NAME.exec(name);
436335
436776
  const rootLegacyMatch = rootLegacyCandidate && /^\d{4}_/u.test(rootLegacyCandidate[3]) && !/^\d{8}_/u.test(rootLegacyCandidate[3]) ? rootLegacyCandidate : void 0;
436336
436777
  const rootLegacyTag = rootLegacyMatch?.[3];
436337
- const explicitRootMillisecond = rootLegacyMatch?.[2] !== void 0;
436338
436778
  const match2 = indexedMatch ?? rootLegacyMatch ?? CANONICAL_JOURNAL_NAME.exec(name);
436339
436779
  if (!match2)
436340
436780
  throw new Error("PLATFORM_MIGRATION_JOURNAL_IDENTITY_INVALID");
@@ -436346,9 +436786,8 @@ function parseJournalIdentity(name, createdAt) {
436346
436786
  const rootDatedLegacy = !indexedMatch && !rootLegacyMatch && /^\d{8}_[a-zA-Z0-9][a-zA-Z0-9._-]*$/u.test(match2[3]);
436347
436787
  const dateMillis = makeUtcMillis(timestamp31.slice(0, 8), "000000000");
436348
436788
  const rootDatedLegacyTimestampIsBounded = rootDatedLegacy && dateMillis !== void 0 && match2[3].slice(0, 8) === timestamp31.slice(0, 8) && expectedCreatedAt !== void 0 && expectedCreatedAt >= dateMillis && expectedCreatedAt < dateMillis + 1e3 && createdAt === dateMillis;
436349
- const rootHistoricalReceipt = explicitRootMillisecond && rootLegacyTag ? ROOT_HISTORICAL_RECEIPTS.get(rootLegacyTag) : void 0;
436350
- const rootHistoricalReceiptIsExact = rootHistoricalReceipt !== void 0 && expectedCreatedAt === rootHistoricalReceipt.timestampMillis && createdAt === rootHistoricalReceipt.createdAt;
436351
- if (expectedCreatedAt === void 0 || !indexedMatch && expectedCreatedAt !== createdAt && !rootDatedLegacyTimestampIsBounded && !rootHistoricalReceiptIsExact)
436789
+ const rootLegacyTimestampIsSameDay = rootLegacyMatch !== void 0 && dateMillis !== void 0 && createdAt >= dateMillis && createdAt < dateMillis + 24 * 60 * 60 * 1e3;
436790
+ if (expectedCreatedAt === void 0 || !indexedMatch && expectedCreatedAt !== createdAt && !rootDatedLegacyTimestampIsBounded && !rootLegacyTimestampIsSameDay)
436352
436791
  throw new Error("PLATFORM_MIGRATION_JOURNAL_IDENTITY_INVALID");
436353
436792
  return {
436354
436793
  dateMillis,
@@ -436356,6 +436795,7 @@ function parseJournalIdentity(name, createdAt) {
436356
436795
  suffix: indexedMatch ? indexedMatch[5] : rootLegacyMatch ? rootLegacyMatch[3].slice(5) : match2[3],
436357
436796
  ...indexedMatch ? { legacyIndexes: [indexedMatch[3], indexedMatch[4]] } : {},
436358
436797
  ...rootLegacyTag ? { rootLegacyTag } : {},
436798
+ ...rootLegacyTimestampIsSameDay ? { rootLegacyTimestampIsSameDay: true } : {},
436359
436799
  ...rootDatedLegacy ? { rootDatedLegacy: true } : {}
436360
436800
  };
436361
436801
  }
@@ -436521,10 +436961,6 @@ function findAppliedFile(row, files, indexes) {
436521
436961
  if (historicalCandidates.length === 1)
436522
436962
  return historicalCandidates[0];
436523
436963
  }
436524
- const rootHistoricalReceipt = identity2.rootLegacyTag && identity2.timestampMillis !== row.createdAt ? ROOT_HISTORICAL_RECEIPTS.get(identity2.rootLegacyTag) : void 0;
436525
- if (rootHistoricalReceipt !== void 0 && identity2.timestampMillis !== row.createdAt && (identity2.timestampMillis !== rootHistoricalReceipt.timestampMillis || row.createdAt !== rootHistoricalReceipt.createdAt)) {
436526
- throw new Error("PLATFORM_MIGRATION_JOURNAL_IDENTITY_INVALID");
436527
- }
436528
436964
  if (identity2.legacyIndexes !== void 0 && (row.createdAt < identity2.timestampMillis || row.createdAt >= identity2.timestampMillis + MAX_INDEXED_LEGACY_CREATED_AT_DRIFT_MS)) {
436529
436965
  throw new Error("PLATFORM_MIGRATION_JOURNAL_IDENTITY_INVALID");
436530
436966
  }
@@ -436549,9 +436985,12 @@ function findAppliedFile(row, files, indexes) {
436549
436985
  }
436550
436986
  }
436551
436987
  if (identity2.rootLegacyTag !== void 0 && exactLegacyIdentity.length === 0) {
436552
- const rootHistoricalReceipt2 = ROOT_HISTORICAL_RECEIPTS.get(identity2.rootLegacyTag);
436553
- if (rootHistoricalReceipt2 !== void 0) {
436988
+ if (exactLegacyIdentity.length === 0 && identity2.rootLegacyTimestampIsSameDay) {
436554
436989
  exactLegacyIdentity = files.filter((file2) => file2.fileName === `${identity2.rootLegacyTag}.sql` && file2.dateMillis === row.createdAt && file2.hash === row.hash);
436990
+ if (exactLegacyIdentity.length > 1)
436991
+ throw new Error("PLATFORM_MIGRATION_SOURCE_AMBIGUOUS");
436992
+ if (exactLegacyIdentity.length === 1)
436993
+ return exactLegacyIdentity[0];
436555
436994
  }
436556
436995
  const canonicalCandidates = files.filter((file2) => {
436557
436996
  const canonical = CANONICAL_MIGRATION_FILE.exec(file2.fileName);
@@ -436577,9 +437016,6 @@ function findAppliedFile(row, files, indexes) {
436577
437016
  })) {
436578
437017
  throw new Error("PLATFORM_MIGRATION_JOURNAL_IDENTITY_INVALID");
436579
437018
  }
436580
- if (rootHistoricalReceipt !== void 0 && exactLegacyIdentity.length === 1 && exactLegacyIdentity[0].fileName === `${identity2.rootLegacyTag}.sql`) {
436581
- return exactLegacyIdentity[0];
436582
- }
436583
437019
  if (exactLegacyIdentity.length === 1 && exactLegacyIdentity[0].hash !== row.hash && identity2.legacyIndexes === void 0 && identity2.rootLegacyTag === void 0) {
436584
437020
  throw new Error("PLATFORM_MIGRATION_SOURCE_HASH_MISMATCH");
436585
437021
  }