@canonry/canonry 7.5.0 → 7.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +8 -0
  2. package/assets/assets/{AuditHistoryPanel-B5aLMnWE.js → AuditHistoryPanel-DZbPVuDn.js} +1 -1
  3. package/assets/assets/{BacklinksPage-Biq1jrqe.js → BacklinksPage-6iPxcQdF.js} +1 -1
  4. package/assets/assets/{HistoryPage-CGGkAgnz.js → HistoryPage-DQ4gqs5s.js} +1 -1
  5. package/assets/assets/{MeasurementPropertyPage-BwyWGGBg.js → MeasurementPropertyPage-X4EGa3a5.js} +1 -1
  6. package/assets/assets/{ProjectPage-DEnKyD3e.js → ProjectPage-qvbLROZz.js} +1 -1
  7. package/assets/assets/{RunsPage-DNBn0Rau.js → RunsPage-DBfy79uf.js} +1 -1
  8. package/assets/assets/{SettingsPage-D3m-BLuf.js → SettingsPage-BlNafKGd.js} +1 -1
  9. package/assets/assets/{SiteHealthSection-CPMu1l-l.js → SiteHealthSection-79l2PnfR.js} +3 -3
  10. package/assets/assets/{TrafficPage-BCK_V__i.js → TrafficPage-CPZWDxjp.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-DaCehUm8.js → TrafficSourceDetailPage-BIhpWiRg.js} +1 -1
  12. package/assets/assets/{extract-error-message-CqBLzzuR.js → extract-error-message-C9XX_kMH.js} +1 -1
  13. package/assets/assets/{index-C2X_UARl.js → index-CUQtRdIf.js} +20 -20
  14. package/assets/assets/{react-sigma_core.esm.min-BvO4SZKT.js → react-sigma_core.esm.min-FTRP6jVQ.js} +1 -1
  15. package/assets/assets/{v2-overview-adapter-CgDChBa5.js → v2-overview-adapter-DEuH0zoM.js} +1 -1
  16. package/assets/index.html +1 -1
  17. package/dist/{chunk-6Z5MRX24.js → chunk-7FJZCG7A.js} +2 -2
  18. package/dist/{chunk-JURAGZOO.js → chunk-B7IT47FE.js} +4 -2
  19. package/dist/{chunk-OY5QVO34.js → chunk-BLHPFAR6.js} +26 -14
  20. package/dist/{chunk-ZHI2MCMD.js → chunk-FRSGZYQZ.js} +433 -278
  21. package/dist/{chunk-E7EWAAH3.js → chunk-HXAGDOYV.js} +3 -3
  22. package/dist/{chunk-KS66E5H6.js → chunk-P72CWNTU.js} +2 -2
  23. package/dist/{chunk-3L7QPB37.js → chunk-WO7XJJHH.js} +5505 -5457
  24. package/dist/cli.js +24 -12
  25. package/dist/{demo-server-55M7DF3U.js → demo-server-Z7NM6DJT.js} +4 -4
  26. package/dist/index.js +6 -6
  27. package/dist/{intelligence-service-HZSRDMFP.js → intelligence-service-P7AOOXLZ.js} +2 -2
  28. package/dist/mcp.js +4 -4
  29. package/package.json +10 -10
@@ -105,6 +105,8 @@ import {
105
105
  POOLED_RUN_ID_LIMIT,
106
106
  PROJECTS_WRITE_SCOPE,
107
107
  PROJECT_OVERVIEW_QUERY_CLASS_SCOPE,
108
+ PROVIDER_ACCOUNT_FAILURE_STREAK,
109
+ PROVIDER_ACCOUNT_RETRY_HOURS,
108
110
  ProviderDispatchModes,
109
111
  READ_ONLY_SCOPE,
110
112
  RESEARCH_RUN_SCOPE,
@@ -447,6 +449,7 @@ import {
447
449
  isBrowserProvider,
448
450
  isLocationRedirectStatus,
449
451
  isNegativeReviewRating,
452
+ isProviderAccountFailure,
450
453
  isReadOnlyKey,
451
454
  isRetryableHttpError,
452
455
  isStrictSemver,
@@ -615,6 +618,7 @@ import {
615
618
  providerDispatchModeSchema,
616
619
  providerError,
617
620
  providerSummaryEntryDtoSchema,
621
+ providersFailing,
618
622
  queryDtoSchema,
619
623
  queryGenerateRequestSchema,
620
624
  queryTrackingCommitRequestSchema,
@@ -796,10 +800,10 @@ import {
796
800
  wordpressSchemaDeployResultDtoSchema,
797
801
  wordpressSchemaStatusResultDtoSchema,
798
802
  wordpressStatusDtoSchema
799
- } from "./chunk-3L7QPB37.js";
803
+ } from "./chunk-WO7XJJHH.js";
800
804
 
801
805
  // src/intelligence-service.ts
802
- import { eq as eq84, desc as desc37, asc as asc15, and as and71, ne as ne15, or as or20, inArray as inArray33, gte as gte22, lte as lte20, isNull as isNull16, sql as sql31, exists as exists2 } from "drizzle-orm";
806
+ import { eq as eq84, desc as desc38, asc as asc15, and as and71, ne as ne15, or as or20, inArray as inArray34, gte as gte22, lte as lte20, isNull as isNull16, sql as sql31, exists as exists2 } from "drizzle-orm";
803
807
 
804
808
  // ../db/src/client.ts
805
809
  import { mkdirSync } from "fs";
@@ -1210,6 +1214,9 @@ var runs = sqliteTable("runs", {
1210
1214
  index("idx_runs_status").on(table.status),
1211
1215
  index("idx_runs_source").on(table.sourceId),
1212
1216
  index("idx_runs_measurement_plan").on(table.projectId, table.measurementPlanVersionId, table.createdAt),
1217
+ // A project's newest runs of one kind: run admission reads ten of them on
1218
+ // every queue (`providerAccountRefusal`), as does the failure-streak count.
1219
+ index("idx_runs_project_kind_created").on(table.projectId, table.kind, table.createdAt),
1213
1220
  foreignKey({
1214
1221
  name: "runs_measurement_plan_version_fk",
1215
1222
  columns: [table.projectId, table.measurementPlanVersionId],
@@ -8165,6 +8172,15 @@ var MIGRATION_VERSIONS = [
8165
8172
  statements: [
8166
8173
  `ALTER TABLE projects ADD COLUMN site_audit_max_pages INTEGER`
8167
8174
  ]
8175
+ },
8176
+ {
8177
+ // Run admission reads a project's ten newest runs of one kind on every
8178
+ // queue; without this it sorted every run the project ever had.
8179
+ version: 170,
8180
+ name: "runs-project-kind-created-index",
8181
+ statements: [
8182
+ `CREATE INDEX IF NOT EXISTS idx_runs_project_kind_created ON runs(project_id, kind, created_at)`
8183
+ ]
8168
8184
  }
8169
8185
  ];
8170
8186
  var AERO_LEDGER_REBUILDS = [
@@ -15288,7 +15304,7 @@ function pruneProviderDispatchModes(modes, providers, revisionProviders) {
15288
15304
 
15289
15305
  // ../api-routes/src/run-queue.ts
15290
15306
  import crypto10 from "crypto";
15291
- import { and as and10, eq as eq16, or as or4 } from "drizzle-orm";
15307
+ import { and as and10, desc as desc7, eq as eq16, gt as gt3, inArray as inArray6, or as or4 } from "drizzle-orm";
15292
15308
 
15293
15309
  // ../api-routes/src/measurement-report-adapter.ts
15294
15310
  import { and as and8, desc as desc5, eq as eq14, gte as gte2, inArray as inArray5, isNull as isNull4, lt as lt4, lte as lte5, ne as ne4 } from "drizzle-orm";
@@ -16907,6 +16923,92 @@ function resolveQueueDispatch(tx, params, stamp) {
16907
16923
  }
16908
16924
  return resolution;
16909
16925
  }
16926
+ function providersARunWouldCall(roster, runnable) {
16927
+ const listed = normalizeProviders(roster);
16928
+ if (runnable == null) return listed;
16929
+ const available = new Set(normalizeProviders(runnable));
16930
+ return listed.filter((provider) => available.has(provider));
16931
+ }
16932
+ var PROVIDER_ACCOUNT_LOOKBACK = PROVIDER_ACCOUNT_FAILURE_STREAK * 5;
16933
+ function providerSettingsChangeCouldFix(action, diff) {
16934
+ if (action === "provider.created") return true;
16935
+ try {
16936
+ const parsed = JSON.parse(diff ?? "null");
16937
+ if (!parsed) return false;
16938
+ if (parsed.apiKeyRotated) return true;
16939
+ const before = parsed.before ?? {};
16940
+ const after = parsed.after ?? {};
16941
+ return before.configured !== after.configured || before.model !== after.model || before.baseUrl !== after.baseUrl;
16942
+ } catch {
16943
+ return false;
16944
+ }
16945
+ }
16946
+ function providerAccountRefusal(db, params) {
16947
+ if (params.force || params.trigger === RunTriggers.probe) return null;
16948
+ const recent = db.select({
16949
+ id: runs.id,
16950
+ status: runs.status,
16951
+ error: runs.error,
16952
+ createdAt: runs.createdAt,
16953
+ finishedAt: runs.finishedAt
16954
+ }).from(runs).where(and10(
16955
+ eq16(runs.projectId, params.projectId),
16956
+ eq16(runs.kind, RunKinds["answer-visibility"]),
16957
+ inArray6(runs.status, [RunStatuses.completed, RunStatuses.partial, RunStatuses.failed, RunStatuses.cancelled])
16958
+ )).orderBy(desc7(runs.createdAt), desc7(runs.id)).limit(PROVIDER_ACCOUNT_LOOKBACK).all().map((run) => ({ ...run, providers: parseRunError(run.error)?.providers ?? {} }));
16959
+ const withAccountFailure = recent.filter((run) => Object.values(run.providers).some((entry) => isProviderAccountFailure(entry.code)));
16960
+ if (withAccountFailure.length < PROVIDER_ACCOUNT_FAILURE_STREAK) return null;
16961
+ const calling = normalizeProviders(params.providers());
16962
+ if (calling.length === 0) return null;
16963
+ const answered2 = (runId, provider) => db.select({ id: querySnapshots.id }).from(querySnapshots).where(and10(eq16(querySnapshots.runId, runId), eq16(querySnapshots.provider, provider))).limit(1).get() !== void 0;
16964
+ const streaks = /* @__PURE__ */ new Map();
16965
+ for (const provider of calling) {
16966
+ let count4 = 0;
16967
+ let newest2 = null;
16968
+ let oldest = null;
16969
+ let code = null;
16970
+ for (const run of recent) {
16971
+ const entry = run.providers[provider];
16972
+ if (!entry) {
16973
+ if (run.status !== RunStatuses.failed && answered2(run.id, provider)) return null;
16974
+ continue;
16975
+ }
16976
+ if (!isProviderAccountFailure(entry.code)) return null;
16977
+ newest2 ??= run;
16978
+ code ??= entry.code;
16979
+ oldest = run;
16980
+ count4 += 1;
16981
+ if (count4 === PROVIDER_ACCOUNT_FAILURE_STREAK) break;
16982
+ }
16983
+ if (count4 < PROVIDER_ACCOUNT_FAILURE_STREAK) return null;
16984
+ streaks.set(provider, { newest: newest2, oldest, code });
16985
+ }
16986
+ const finished = (run) => Date.parse(run.finishedAt ?? run.createdAt);
16987
+ const newest = [...streaks.values()].map((streak) => streak.newest).sort((a, b) => finished(b) - finished(a))[0];
16988
+ const retryAfterMs = finished(newest) + PROVIDER_ACCOUNT_RETRY_HOURS * 36e5;
16989
+ if (Date.parse(params.now) >= retryAfterMs) return null;
16990
+ const since = [...streaks.values()].map((streak) => streak.oldest.createdAt).sort()[0];
16991
+ const settingsChanges = db.select({ entityId: auditLog.entityId, action: auditLog.action, diff: auditLog.diff, createdAt: auditLog.createdAt }).from(auditLog).where(and10(eq16(auditLog.entityType, "provider"), inArray6(auditLog.entityId, calling), gt3(auditLog.createdAt, since))).all();
16992
+ const fixedSince = settingsChanges.some((change) => {
16993
+ const streak = streaks.get(change.entityId ?? "");
16994
+ return streak !== void 0 && change.createdAt > streak.oldest.createdAt && providerSettingsChangeCouldFix(change.action, change.diff);
16995
+ });
16996
+ if (fixedSince) return null;
16997
+ return {
16998
+ consecutiveRuns: PROVIDER_ACCOUNT_FAILURE_STREAK,
16999
+ latestRunId: newest.id,
17000
+ since,
17001
+ retryAfter: new Date(retryAfterMs).toISOString(),
17002
+ providers: Object.fromEntries(calling.map((provider) => [provider, streaks.get(provider).code]))
17003
+ };
17004
+ }
17005
+ function providersFailingError(projectName, failures) {
17006
+ const named = Object.entries(failures.providers).map(([provider, code]) => `${provider} (${code})`).join(", ");
17007
+ return providersFailing(
17008
+ `Not starting a run for '${projectName}': every provider it would call failed on its account (a rejected key, denied access, or no credit left) in each of its last ${failures.consecutiveRuns} runs: ${named}. Fix it in the provider's console or settings. Saving a new key, model or endpoint for the provider (canonry settings provider <name>) lets the next run through; otherwise one run is let through after ${failures.retryAfter}. Pass force (canonry run --force) to run now.`,
17009
+ { projectName, ...failures }
17010
+ );
17011
+ }
16910
17012
  function queueRunIfProjectIdle(db, params) {
16911
17013
  const createdAt = params.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
16912
17014
  const kind = params.kind ?? "answer-visibility";
@@ -16947,6 +17049,17 @@ function queueRunIfProjectIdle(db, params) {
16947
17049
  }
16948
17050
  const current = activeRun();
16949
17051
  if (current) return { conflict: true, activeRunId: current.id };
17052
+ const refused = kind === RunKinds["answer-visibility"] ? providerAccountRefusal(tx, {
17053
+ projectId: params.projectId,
17054
+ trigger: stamp?.scope ? RunTriggers.probe : trigger,
17055
+ force: params.force ?? false,
17056
+ now: createdAt,
17057
+ providers: () => providersARunWouldCall(
17058
+ stamp?.identity.providers ?? providerRoster(tx, params),
17059
+ params.runnableProviders
17060
+ )
17061
+ }) : null;
17062
+ if (refused) return { conflict: false, refused };
16950
17063
  const scoped = params.queries != null || stamp?.scope != null;
16951
17064
  const basket = scoped ? null : ensureCurrentQueryBasketRevision(tx, params.projectId, createdAt);
16952
17065
  tx.insert(runs).values({
@@ -16978,7 +17091,7 @@ function queueRunIfProjectIdle(db, params) {
16978
17091
  }
16979
17092
 
16980
17093
  // ../api-routes/src/provider-batches.ts
16981
- import { and as and11, asc as asc2, eq as eq17, inArray as inArray6 } from "drizzle-orm";
17094
+ import { and as and11, asc as asc2, eq as eq17, inArray as inArray7 } from "drizzle-orm";
16982
17095
  function formatProviderBatchSummary(row) {
16983
17096
  return {
16984
17097
  id: row.id,
@@ -17001,10 +17114,10 @@ function runHadProviderBatch(db, runId) {
17001
17114
  return db.select({ id: providerBatches.id }).from(providerBatches).where(eq17(providerBatches.runId, runId)).limit(1).get() !== void 0;
17002
17115
  }
17003
17116
  function hasOutstandingProviderBatch(db, runId) {
17004
- return db.select({ id: providerBatches.id }).from(providerBatches).where(and11(eq17(providerBatches.runId, runId), inArray6(providerBatches.status, [...OUTSTANDING_PROVIDER_BATCH_STATUSES]))).limit(1).get() !== void 0;
17117
+ return db.select({ id: providerBatches.id }).from(providerBatches).where(and11(eq17(providerBatches.runId, runId), inArray7(providerBatches.status, [...OUTSTANDING_PROVIDER_BATCH_STATUSES]))).limit(1).get() !== void 0;
17005
17118
  }
17006
17119
  function readProjectRunsWithOutstandingProviderBatch(db, projectId) {
17007
- return db.selectDistinct({ runId: providerBatches.runId }).from(providerBatches).where(and11(eq17(providerBatches.projectId, projectId), inArray6(providerBatches.status, [...OUTSTANDING_PROVIDER_BATCH_STATUSES]))).orderBy(asc2(providerBatches.runId)).all().map((row) => row.runId);
17120
+ return db.selectDistinct({ runId: providerBatches.runId }).from(providerBatches).where(and11(eq17(providerBatches.projectId, projectId), inArray7(providerBatches.status, [...OUTSTANDING_PROVIDER_BATCH_STATUSES]))).orderBy(asc2(providerBatches.runId)).all().map((row) => row.runId);
17008
17121
  }
17009
17122
 
17010
17123
  // ../api-routes/src/projects.ts
@@ -17571,13 +17684,13 @@ function aliasArraysEqual(a, b) {
17571
17684
 
17572
17685
  // ../api-routes/src/queries.ts
17573
17686
  import crypto13 from "crypto";
17574
- import { and as and14, eq as eq20, inArray as inArray8, sql as sql8 } from "drizzle-orm";
17687
+ import { and as and14, eq as eq20, inArray as inArray9, sql as sql8 } from "drizzle-orm";
17575
17688
 
17576
17689
  // ../api-routes/src/query-replace.ts
17577
17690
  import crypto12 from "crypto";
17578
- import { and as and13, eq as eq19, inArray as inArray7, isNull as isNull5 } from "drizzle-orm";
17691
+ import { and as and13, eq as eq19, inArray as inArray8, isNull as isNull5 } from "drizzle-orm";
17579
17692
  function preserveSnapshotQueryText(tx, projectId, queryIds) {
17580
- const candidates = queryIds && queryIds.length > 0 ? tx.select({ id: queries.id, text: queries.query }).from(queries).where(and13(eq19(queries.projectId, projectId), inArray7(queries.id, queryIds))).all() : tx.select({ id: queries.id, text: queries.query }).from(queries).where(eq19(queries.projectId, projectId)).all();
17693
+ const candidates = queryIds && queryIds.length > 0 ? tx.select({ id: queries.id, text: queries.query }).from(queries).where(and13(eq19(queries.projectId, projectId), inArray8(queries.id, queryIds))).all() : tx.select({ id: queries.id, text: queries.query }).from(queries).where(eq19(queries.projectId, projectId)).all();
17581
17694
  for (const q of candidates) {
17582
17695
  tx.update(querySnapshots).set({ queryText: q.text }).where(and13(eq19(querySnapshots.queryId, q.id), isNull5(querySnapshots.queryText))).run();
17583
17696
  }
@@ -17640,7 +17753,7 @@ function assertNoActivePlanlessSweep(tx, scope) {
17640
17753
  const activeRun = tx.select({ id: runs.id }).from(runs).where(and13(
17641
17754
  eq19(runs.projectId, scope.projectId),
17642
17755
  eq19(runs.kind, RunKinds["answer-visibility"]),
17643
- inArray7(runs.status, [RunStatuses.queued, RunStatuses.running]),
17756
+ inArray8(runs.status, [RunStatuses.queued, RunStatuses.running]),
17644
17757
  isNull5(runs.measurementPlanVersionId)
17645
17758
  )).get();
17646
17759
  if (activeRun) throw runInProgress(scope.projectName, RunKinds["answer-visibility"], activeRun.id);
@@ -17693,11 +17806,11 @@ function replaceProjectQueries(tx, projectId, incomingTexts, now) {
17693
17806
  for (const dup of diff.duplicates) {
17694
17807
  tx.update(querySnapshots).set({ queryId: dup.keptId }).where(eq19(querySnapshots.queryId, dup.id)).run();
17695
17808
  }
17696
- tx.delete(queries).where(inArray7(queries.id, diff.duplicates.map((d) => d.id))).run();
17809
+ tx.delete(queries).where(inArray8(queries.id, diff.duplicates.map((d) => d.id))).run();
17697
17810
  }
17698
17811
  if (diff.removed.length > 0) {
17699
17812
  const removedIds = diff.removed.map((r) => r.id);
17700
- tx.delete(queries).where(inArray7(queries.id, removedIds)).run();
17813
+ tx.delete(queries).where(inArray8(queries.id, removedIds)).run();
17701
17814
  }
17702
17815
  for (const keptRow of diff.kept) {
17703
17816
  if (keptRow.currentText !== keptRow.incomingText) {
@@ -17721,7 +17834,11 @@ function generationFailure(err, fallbackMessage) {
17721
17834
  if (err instanceof AppError) return err;
17722
17835
  const message = err instanceof Error ? describeError(err) : fallbackMessage;
17723
17836
  switch (classifyProviderErrorMessage(message)) {
17837
+ // Billing has no error code of its own on the wire. It is an account
17838
+ // problem the operator fixes in the provider's console, as with a bad key,
17839
+ // and not a limit to wait out; the message names which one it is.
17724
17840
  case "PROVIDER_AUTH":
17841
+ case "PROVIDER_BILLING":
17725
17842
  return providerAuthError(message);
17726
17843
  case "RATE_LIMITED":
17727
17844
  return quotaExceeded("provider requests", { message });
@@ -17788,9 +17905,9 @@ async function queryRoutes(app, opts) {
17788
17905
  let snapshotsDetached = 0;
17789
17906
  let affectedQueries = 0;
17790
17907
  if (removedIds.length > 0) {
17791
- const snapshotCount = app.db.select({ n: sql8`count(*)` }).from(querySnapshots).where(inArray8(querySnapshots.queryId, removedIds)).get();
17908
+ const snapshotCount = app.db.select({ n: sql8`count(*)` }).from(querySnapshots).where(inArray9(querySnapshots.queryId, removedIds)).get();
17792
17909
  snapshotsDetached = snapshotCount?.n ?? 0;
17793
- const distinctAffected = app.db.select({ n: sql8`count(distinct ${querySnapshots.queryId})` }).from(querySnapshots).where(inArray8(querySnapshots.queryId, removedIds)).get();
17910
+ const distinctAffected = app.db.select({ n: sql8`count(distinct ${querySnapshots.queryId})` }).from(querySnapshots).where(inArray9(querySnapshots.queryId, removedIds)).get();
17794
17911
  affectedQueries = distinctAffected?.n ?? 0;
17795
17912
  }
17796
17913
  return reply.send({
@@ -18240,7 +18357,7 @@ function parseBody(schema, value, message) {
18240
18357
  }
18241
18358
 
18242
18359
  // ../api-routes/src/competitor-landscape.ts
18243
- import { and as and17, desc as desc7, eq as eq24, gte as gte3, inArray as inArray9, isNull as isNull6 } from "drizzle-orm";
18360
+ import { and as and17, desc as desc8, eq as eq24, gte as gte3, inArray as inArray10, isNull as isNull6 } from "drizzle-orm";
18244
18361
 
18245
18362
  // ../api-routes/src/mention-share-inputs.ts
18246
18363
  import { eq as eq22 } from "drizzle-orm";
@@ -19053,11 +19170,11 @@ function latestSweepRuns(db, projectId) {
19053
19170
  const candidates = db.select().from(runs).where(and17(
19054
19171
  eq24(runs.projectId, projectId),
19055
19172
  eq24(runs.kind, RunKinds["answer-visibility"]),
19056
- inArray9(runs.status, [RunStatuses.completed, RunStatuses.partial]),
19173
+ inArray10(runs.status, [RunStatuses.completed, RunStatuses.partial]),
19057
19174
  notProbeRun(),
19058
19175
  // A scoped spot check is never the latest sweep.
19059
19176
  isNull6(runs.measurementScope)
19060
- )).orderBy(desc7(runs.createdAt), desc7(runs.id)).all();
19177
+ )).orderBy(desc8(runs.createdAt), desc8(runs.id)).all();
19061
19178
  for (const group of groupRunsByCreatedAt(candidates)) {
19062
19179
  const whole = group.filter((run) => measurementRunCompleteness(db, run.id).complete);
19063
19180
  if (whole.length > 0) return whole;
@@ -19082,8 +19199,8 @@ function readCompetitorLandscape(app, projectName, query, selection) {
19082
19199
  const candidateRuns = app.db.select().from(runs).where(and17(
19083
19200
  eq24(runs.projectId, project.id),
19084
19201
  eq24(runs.kind, RunKinds["answer-visibility"]),
19085
- selection ? inArray9(runs.id, [...selection.runIds]) : void 0,
19086
- latestRunIds ? inArray9(runs.id, latestRunIds) : filters.runId ? eq24(runs.id, filters.runId) : void 0,
19202
+ selection ? inArray10(runs.id, [...selection.runIds]) : void 0,
19203
+ latestRunIds ? inArray10(runs.id, latestRunIds) : filters.runId ? eq24(runs.id, filters.runId) : void 0,
19087
19204
  cutoff ? gte3(runs.createdAt, cutoff) : void 0
19088
19205
  )).all();
19089
19206
  const advanced = filters.groupKey || filters.scope === "all-markets" ? resolveAdvancedScope(app, project.id, filters.groupKey ? "group" : "all-markets", filters.groupKey, candidateRuns) : null;
@@ -19111,7 +19228,7 @@ function readCompetitorLandscape(app, projectName, query, selection) {
19111
19228
  location: querySnapshots.location,
19112
19229
  measurementExecutionId: querySnapshots.measurementExecutionId,
19113
19230
  createdAt: querySnapshots.createdAt
19114
- }).from(querySnapshots).where(inArray9(querySnapshots.runId, candidateRuns.map((run) => run.id))).all();
19231
+ }).from(querySnapshots).where(inArray10(querySnapshots.runId, candidateRuns.map((run) => run.id))).all();
19115
19232
  const runById = new Map(candidateRuns.map((run) => [run.id, run]));
19116
19233
  const selectedIds = selection?.snapshotIds ? new Set(selection.snapshotIds) : null;
19117
19234
  const inScope = allSnapshots.filter((snapshot) => (!selectedIds || selectedIds.has(snapshot.id)) && snapshotMatchesFilters({
@@ -19295,7 +19412,7 @@ function frozenRunScopes(db, projectId, kind, groupKey, candidateRuns) {
19295
19412
  const planVersionIds = [...new Set(candidateRuns.map((run) => run.measurementPlanVersionId).filter((id) => typeof id === "string" && id.length > 0))];
19296
19413
  const historicalVersions = planVersionIds.length === 0 ? [] : db.select().from(measurementPlanVersions).where(and17(
19297
19414
  eq24(measurementPlanVersions.projectId, projectId),
19298
- inArray9(measurementPlanVersions.id, planVersionIds)
19415
+ inArray10(measurementPlanVersions.id, planVersionIds)
19299
19416
  )).all();
19300
19417
  const frozenByVersionId = new Map(historicalVersions.map((version) => [
19301
19418
  version.id,
@@ -19433,12 +19550,12 @@ function mergePins(...collections) {
19433
19550
 
19434
19551
  // ../api-routes/src/runs.ts
19435
19552
  import crypto15 from "crypto";
19436
- import { and as and19, eq as eq26, asc as asc3, desc as desc9, inArray as inArray11, or as or6, sql as sql10 } from "drizzle-orm";
19553
+ import { and as and19, eq as eq26, asc as asc3, desc as desc10, inArray as inArray12, or as or6, sql as sql10 } from "drizzle-orm";
19437
19554
  import { gte as gte4 } from "drizzle-orm";
19438
19555
 
19439
19556
  // ../api-routes/src/run-fill.ts
19440
19557
  import crypto14 from "crypto";
19441
- import { and as and18, desc as desc8, eq as eq25, gt as gt3, inArray as inArray10, isNull as isNull7, ne as ne5, or as or5, sql as sql9 } from "drizzle-orm";
19558
+ import { and as and18, desc as desc9, eq as eq25, gt as gt4, inArray as inArray11, isNull as isNull7, ne as ne5, or as or5, sql as sql9 } from "drizzle-orm";
19442
19559
  var ACTIVE_STATUSES = ["queued", "running"];
19443
19560
  function normalizeProvider(value) {
19444
19561
  return value.trim().toLocaleLowerCase("en");
@@ -19466,12 +19583,12 @@ function newerFullSweep(db, run) {
19466
19583
  ne5(runs.trigger, RunTriggers.probe),
19467
19584
  isNull7(runs.measurementScope),
19468
19585
  isNull7(runs.queries),
19469
- gt3(runs.createdAt, run.createdAt),
19586
+ gt4(runs.createdAt, run.createdAt),
19470
19587
  or5(
19471
- inArray10(runs.status, ["queued", "running", "completed", "partial"]),
19588
+ inArray11(runs.status, ["queued", "running", "completed", "partial"]),
19472
19589
  sql9`EXISTS (SELECT 1 FROM ${querySnapshots} WHERE ${querySnapshots.runId} = ${runs.id})`
19473
19590
  )
19474
- )).orderBy(desc8(runs.createdAt)).get();
19591
+ )).orderBy(desc9(runs.createdAt)).get();
19475
19592
  }
19476
19593
  function measuredOnRetiredModel(run, provider, missing) {
19477
19594
  const recorded = run.measurementExecutionIdentity?.models[provider];
@@ -19607,16 +19724,16 @@ function evaluateRunFill(db, run, input = {}) {
19607
19724
  return { kind: "fillable", slots, providers, missing };
19608
19725
  }
19609
19726
  function latestFillFor(db, runId) {
19610
- return db.select().from(runFills).where(eq25(runFills.runId, runId)).orderBy(desc8(runFills.createdAt), desc8(runFills.id)).get();
19727
+ return db.select().from(runFills).where(eq25(runFills.runId, runId)).orderBy(desc9(runFills.createdAt), desc9(runFills.id)).get();
19611
19728
  }
19612
19729
  function activeFillFor(db, projectId) {
19613
- return db.select().from(runFills).where(and18(eq25(runFills.projectId, projectId), inArray10(runFills.status, [...ACTIVE_STATUSES]))).get();
19730
+ return db.select().from(runFills).where(and18(eq25(runFills.projectId, projectId), inArray11(runFills.status, [...ACTIVE_STATUSES]))).get();
19614
19731
  }
19615
19732
  function activeSweepFor(db, projectId) {
19616
19733
  return db.select({ id: runs.id }).from(runs).where(and18(
19617
19734
  eq25(runs.projectId, projectId),
19618
19735
  eq25(runs.kind, RunKinds["answer-visibility"]),
19619
- inArray10(runs.status, [...ACTIVE_STATUSES])
19736
+ inArray11(runs.status, [...ACTIVE_STATUSES])
19620
19737
  )).get();
19621
19738
  }
19622
19739
  function readRunCompleteness(db, run, input = {}) {
@@ -19789,6 +19906,22 @@ async function runRoutes(app, opts) {
19789
19906
  if (activeRun) {
19790
19907
  return { conflict: true, activeRunId: activeRun.id };
19791
19908
  }
19909
+ const refused = providerAccountRefusal(tx, {
19910
+ projectId: project.id,
19911
+ trigger,
19912
+ force: body.force ?? false,
19913
+ now,
19914
+ providers: () => {
19915
+ const runnable = opts.getRunnableProviderNames?.();
19916
+ const roster = resolveRunnableProviderSelection({
19917
+ requestedProviders: providers,
19918
+ projectProviders: project.providers,
19919
+ runnableProviders: runnable
19920
+ }).selectedProviders;
19921
+ return providersARunWouldCall(roster, runnable);
19922
+ }
19923
+ });
19924
+ if (refused) return { conflict: false, refused };
19792
19925
  const inserted = [];
19793
19926
  for (const loc of projectLocations) {
19794
19927
  const runId2 = crypto15.randomUUID();
@@ -19809,6 +19942,7 @@ async function runRoutes(app, opts) {
19809
19942
  if (result.conflict) {
19810
19943
  throw runInProgress(project.name, kind, result.activeRunId);
19811
19944
  }
19945
+ if (result.refused) throw providersFailingError(project.name, result.refused);
19812
19946
  const results = [];
19813
19947
  for (const { runId: runId2, loc } of result.inserted) {
19814
19948
  writeAuditLog(app.db, {
@@ -19839,9 +19973,11 @@ async function runRoutes(app, opts) {
19839
19973
  providerModels: opts.getEffectiveProviderModels?.(),
19840
19974
  measurementScope: body.measurementScope ?? null,
19841
19975
  dispatchMode: body.dispatchMode ?? null,
19842
- batchEligibleProviders: opts.getBatchEligibleProviderNames?.() ?? null
19976
+ batchEligibleProviders: opts.getBatchEligibleProviderNames?.() ?? null,
19977
+ force: body.force ?? false
19843
19978
  });
19844
19979
  if (queueResult.conflict) throw runInProgress(project.name, kind, queueResult.activeRunId);
19980
+ if (queueResult.refused) throw providersFailingError(project.name, queueResult.refused);
19845
19981
  const runId = queueResult.runId;
19846
19982
  writeAuditLog(app.db, {
19847
19983
  projectId: project.id,
@@ -19865,14 +20001,14 @@ async function runRoutes(app, opts) {
19865
20001
  if (kind) filters.push(eq26(runs.kind, kind));
19866
20002
  if (status) filters.push(eq26(runs.status, status));
19867
20003
  const where = and19(...filters);
19868
- const rows = limit == null ? app.db.select().from(runs).where(where).orderBy(asc3(runs.createdAt)).all() : app.db.select().from(runs).where(where).orderBy(desc9(runs.createdAt)).limit(limit).all().reverse();
20004
+ const rows = limit == null ? app.db.select().from(runs).where(where).orderBy(asc3(runs.createdAt)).all() : app.db.select().from(runs).where(where).orderBy(desc10(runs.createdAt)).limit(limit).all().reverse();
19869
20005
  return reply.send(rows.map(formatRun));
19870
20006
  });
19871
20007
  app.get("/projects/:name/runs/latest", async (request, reply) => {
19872
20008
  const project = resolveProject(app.db, request.params.name);
19873
20009
  const countRow = app.db.select({ count: sql10`count(*)` }).from(runs).where(and19(eq26(runs.projectId, project.id), notProbeRun())).get();
19874
20010
  const totalRuns = countRow?.count ?? 0;
19875
- const latestRun = app.db.select().from(runs).where(and19(eq26(runs.projectId, project.id), notProbeRun())).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(1).get();
20011
+ const latestRun = app.db.select().from(runs).where(and19(eq26(runs.projectId, project.id), notProbeRun())).orderBy(desc10(runs.createdAt), desc10(runs.id)).limit(1).get();
19876
20012
  if (!latestRun) {
19877
20013
  return reply.send({ totalRuns: 0, run: null });
19878
20014
  }
@@ -19892,7 +20028,7 @@ async function runRoutes(app, opts) {
19892
20028
  if (status) filters.push(eq26(runs.status, status));
19893
20029
  const scopedProjectId = request.apiKey?.projectId;
19894
20030
  if (scopedProjectId) filters.push(eq26(runs.projectId, scopedProjectId));
19895
- const rows = app.db.select().from(runs).where(and19(...filters)).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(limit).all();
20031
+ const rows = app.db.select().from(runs).where(and19(...filters)).orderBy(desc10(runs.createdAt), desc10(runs.id)).limit(limit).all();
19896
20032
  return reply.send(rows.map(formatRun));
19897
20033
  });
19898
20034
  app.post("/runs", async (request, reply) => {
@@ -19909,6 +20045,8 @@ async function runRoutes(app, opts) {
19909
20045
  }
19910
20046
  const dispatchMode = parsedDispatchMode.data ?? null;
19911
20047
  const batchEligibleProviders = opts.getBatchEligibleProviderNames?.() ?? null;
20048
+ const force = request.body?.force;
20049
+ if (force !== void 0 && typeof force !== "boolean") throw validationError('"force" must be a boolean');
19912
20050
  const rawProviders = request.body?.providers;
19913
20051
  if (rawProviders?.length) {
19914
20052
  const normalized = rawProviders.map((p) => p.trim().toLowerCase()).filter(Boolean);
@@ -20004,12 +20142,18 @@ async function runRoutes(app, opts) {
20004
20142
  runnableProviders: runnableProviderNames,
20005
20143
  providerModels: opts.getEffectiveProviderModels?.(),
20006
20144
  dispatchMode,
20007
- batchEligibleProviders
20145
+ batchEligibleProviders,
20146
+ force: force ?? false
20008
20147
  });
20009
20148
  if (queueResult.conflict) {
20010
20149
  results.push({ projectName: project.name, projectId: project.id, status: "conflict", error: "run_in_progress" });
20011
20150
  continue;
20012
20151
  }
20152
+ if (queueResult.refused) {
20153
+ const refusal = providersFailingError(project.name, queueResult.refused);
20154
+ results.push({ projectName: project.name, projectId: project.id, status: "error", error: refusal.message, errorCode: refusal.code });
20155
+ continue;
20156
+ }
20013
20157
  const runId = queueResult.runId;
20014
20158
  writeAuditLog(app.db, {
20015
20159
  projectId: project.id,
@@ -20033,7 +20177,7 @@ async function runRoutes(app, opts) {
20033
20177
  const terminalStatuses = /* @__PURE__ */ new Set(["completed", "partial", "failed", "cancelled"]);
20034
20178
  if (terminalStatuses.has(run.status)) throw runNotCancellable(run.id, run.status);
20035
20179
  const now = (/* @__PURE__ */ new Date()).toISOString();
20036
- const cancelled = app.db.update(runs).set({ status: "cancelled", finishedAt: now, error: serializeRunError({ message: "Cancelled by user" }) }).where(and19(eq26(runs.id, run.id), inArray11(runs.status, ["queued", "running"]))).run();
20180
+ const cancelled = app.db.update(runs).set({ status: "cancelled", finishedAt: now, error: serializeRunError({ message: "Cancelled by user" }) }).where(and19(eq26(runs.id, run.id), inArray12(runs.status, ["queued", "running"]))).run();
20037
20181
  if (cancelled.changes === 0) {
20038
20182
  const current = app.db.select().from(runs).where(eq26(runs.id, run.id)).get();
20039
20183
  if (!current) throw notFound("Run", run.id);
@@ -20299,7 +20443,7 @@ function loadRunDetail(app, run) {
20299
20443
 
20300
20444
  // ../api-routes/src/measurement-plan.ts
20301
20445
  import crypto16 from "crypto";
20302
- import { and as and20, desc as desc10, eq as eq27 } from "drizzle-orm";
20446
+ import { and as and20, desc as desc11, eq as eq27 } from "drizzle-orm";
20303
20447
  var MEASUREMENT_PLAN_WRITE_SCOPE = "measurement-plan.write";
20304
20448
  function parseStoredPlanAnyVersion(canonicalJson3) {
20305
20449
  return parseStoredMeasurementPlanAnyVersion(canonicalJson3);
@@ -20656,7 +20800,7 @@ async function measurementPlanRoutes(app, opts) {
20656
20800
  app.get("/projects/:name/measurement-plan/versions", async (request) => {
20657
20801
  const project = resolveProject(app.db, request.params.name);
20658
20802
  const active = activePlanVersion(app, project.id);
20659
- const versions = app.db.select().from(measurementPlanVersions).where(eq27(measurementPlanVersions.projectId, project.id)).orderBy(desc10(measurementPlanVersions.revision)).all();
20803
+ const versions = app.db.select().from(measurementPlanVersions).where(eq27(measurementPlanVersions.projectId, project.id)).orderBy(desc11(measurementPlanVersions.revision)).all();
20660
20804
  return {
20661
20805
  versions: versions.map((version) => versionMetadata(version, active?.version.id ?? null))
20662
20806
  };
@@ -21397,7 +21541,7 @@ async function measurementServiceRoutes(app, opts) {
21397
21541
 
21398
21542
  // ../api-routes/src/measurement-draft.ts
21399
21543
  import crypto19 from "crypto";
21400
- import { and as and21, asc as asc4, desc as desc11, eq as eq28, inArray as inArray12 } from "drizzle-orm";
21544
+ import { and as and21, asc as asc4, desc as desc12, eq as eq28, inArray as inArray13 } from "drizzle-orm";
21401
21545
 
21402
21546
  // ../api-routes/src/measurement-draft-compile.ts
21403
21547
  var MEASUREMENT_DRAFT_MAX_TARGETS = 1e3;
@@ -23549,7 +23693,7 @@ async function measurementDraftRoutes(app, opts = {}) {
23549
23693
  // The comparable chain, not the bare active id: a label-only
23550
23694
  // republish must not flip setup back to awaiting_first_run while
23551
23695
  // the overview keeps serving the prior run.
23552
- inArray12(runs.measurementPlanVersionId, comparableMeasurementVersionIds(app.db, project.id, active.id)),
23696
+ inArray13(runs.measurementPlanVersionId, comparableMeasurementVersionIds(app.db, project.id, active.id)),
23553
23697
  eq28(runs.status, RunStatuses.completed)
23554
23698
  )).get() : void 0;
23555
23699
  const state = activeSchemaVersion === 1 ? "republish_required" : draft ? "setup_in_progress" : active ? completedRun ? "operational" : "awaiting_first_run" : "simple";
@@ -24034,7 +24178,7 @@ async function measurementDraftRoutes(app, opts = {}) {
24034
24178
  }));
24035
24179
  return settle(false, active, parseV2Plan(active));
24036
24180
  }
24037
- const latest = tx.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq28(measurementPlanVersions.projectId, gate.project.id)).orderBy(desc11(measurementPlanVersions.revision)).get();
24181
+ const latest = tx.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq28(measurementPlanVersions.projectId, gate.project.id)).orderBy(desc12(measurementPlanVersions.revision)).get();
24038
24182
  const revision = (latest?.revision ?? 0) + 1;
24039
24183
  const canonicalJson3 = canonicalMeasurementPlanV2Json(compiled.plan);
24040
24184
  const versionId = crypto19.randomUUID();
@@ -24171,7 +24315,7 @@ async function measurementDraftRoutes(app, opts = {}) {
24171
24315
  const sets = app.db.select().from(measurementQuerySets).where(eq28(measurementQuerySets.projectId, project.id)).orderBy(asc4(measurementQuerySets.name)).all();
24172
24316
  const counts2 = /* @__PURE__ */ new Map();
24173
24317
  if (sets.length) {
24174
- for (const item2 of app.db.select({ querySetId: measurementQuerySetItems.querySetId }).from(measurementQuerySetItems).where(inArray12(measurementQuerySetItems.querySetId, sets.map((set) => set.id))).all()) {
24318
+ for (const item2 of app.db.select({ querySetId: measurementQuerySetItems.querySetId }).from(measurementQuerySetItems).where(inArray13(measurementQuerySetItems.querySetId, sets.map((set) => set.id))).all()) {
24175
24319
  counts2.set(item2.querySetId, (counts2.get(item2.querySetId) ?? 0) + 1);
24176
24320
  }
24177
24321
  }
@@ -24400,7 +24544,7 @@ async function measurementDraftRoutes(app, opts = {}) {
24400
24544
  diff: { created: created.length, existing: existing.length }
24401
24545
  }));
24402
24546
  if (!querySet) return;
24403
- const highest = tx.select({ position: measurementQuerySetItems.position }).from(measurementQuerySetItems).where(eq28(measurementQuerySetItems.querySetId, querySet.id)).orderBy(desc11(measurementQuerySetItems.position)).get();
24547
+ const highest = tx.select({ position: measurementQuerySetItems.position }).from(measurementQuerySetItems).where(eq28(measurementQuerySetItems.querySetId, querySet.id)).orderBy(desc12(measurementQuerySetItems.position)).get();
24404
24548
  let position = (highest?.position ?? -1) + 1;
24405
24549
  const present = new Set(tx.select({ queryId: measurementQuerySetItems.queryId }).from(measurementQuerySetItems).where(eq28(measurementQuerySetItems.querySetId, querySet.id)).all().map((item2) => item2.queryId));
24406
24550
  for (const entry of ordered) {
@@ -25073,10 +25217,10 @@ async function measurementPropertyEvidenceRoutes(app) {
25073
25217
  }
25074
25218
 
25075
25219
  // ../api-routes/src/measurement-portfolio-reads.ts
25076
- import { and as and25, desc as desc12, eq as eq32, inArray as inArray14, lt as lt5, or as or7 } from "drizzle-orm";
25220
+ import { and as and25, desc as desc13, eq as eq32, inArray as inArray15, lt as lt5, or as or7 } from "drizzle-orm";
25077
25221
 
25078
25222
  // ../api-routes/src/measurement-question-reads.ts
25079
- import { and as and24, eq as eq31, getTableColumns, inArray as inArray13, sql as sql11 } from "drizzle-orm";
25223
+ import { and as and24, eq as eq31, getTableColumns, inArray as inArray14, sql as sql11 } from "drizzle-orm";
25080
25224
  var DEFAULT_LIMIT2 = 50;
25081
25225
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
25082
25226
  RunStatuses.completed,
@@ -25192,7 +25336,7 @@ function selectedQuestionSnapshots(db, runId, manifest, scope) {
25192
25336
  if (scope !== void 0) {
25193
25337
  const executionIds = [...new Set(manifest.expectedSlots.map((slot) => slot.executionId))];
25194
25338
  if (executionIds.length === 0) return [];
25195
- conditions.push(inArray13(querySnapshots.measurementExecutionId, executionIds));
25339
+ conditions.push(inArray14(querySnapshots.measurementExecutionId, executionIds));
25196
25340
  }
25197
25341
  if (scope?.provider !== void 0) {
25198
25342
  conditions.push(sql11`lower(trim(${querySnapshots.provider})) = ${normalizeText(scope.provider)}`);
@@ -25207,7 +25351,7 @@ function rawResponsesForLegacyQuestionSnapshots(db, runId, snapshots) {
25207
25351
  rawResponse: querySnapshots.rawResponse
25208
25352
  }).from(querySnapshots).where(and24(
25209
25353
  eq31(querySnapshots.runId, runId),
25210
- inArray13(querySnapshots.id, legacyIds)
25354
+ inArray14(querySnapshots.id, legacyIds)
25211
25355
  )).all().map((snapshot) => [snapshot.id, snapshot.rawResponse]));
25212
25356
  }
25213
25357
  function withLegacyRawEvidence(db, runId, snapshots) {
@@ -26136,14 +26280,14 @@ function previousComparableRun(db, active, current) {
26136
26280
  // republish: a run pinned to a comparable prior revision measured exactly
26137
26281
  // the questions the active revision asks. The execution-identity and scope
26138
26282
  // checks below still gate what actually compares.
26139
- inArray14(runs.measurementPlanVersionId, comparableMeasurementVersionIds(db, current.projectId, active.version.id)),
26283
+ inArray15(runs.measurementPlanVersionId, comparableMeasurementVersionIds(db, current.projectId, active.version.id)),
26140
26284
  eq32(runs.kind, RunKinds["answer-visibility"]),
26141
- inArray14(runs.status, [RunStatuses.completed, RunStatuses.partial]),
26285
+ inArray15(runs.status, [RunStatuses.completed, RunStatuses.partial]),
26142
26286
  or7(
26143
26287
  lt5(runs.createdAt, current.createdAt),
26144
26288
  and25(eq32(runs.createdAt, current.createdAt), lt5(runs.id, current.id))
26145
26289
  )
26146
- )).orderBy(desc12(runs.createdAt), desc12(runs.id)).all().filter((candidate) => (
26290
+ )).orderBy(desc13(runs.createdAt), desc13(runs.id)).all().filter((candidate) => (
26147
26291
  // Full reporting never admits probes. A plan slice is itself stored as a
26148
26292
  // probe, so an explicitly selected slice compares only with other slices;
26149
26293
  // the exact frozen scope check below then keeps the population identical.
@@ -26395,7 +26539,7 @@ function unattributedByClass(plan, run, materialized) {
26395
26539
  return { branded: read("branded"), nonBrand: read("non-brand") };
26396
26540
  }
26397
26541
  function latestRunFill(db, runId) {
26398
- const fill = db.select().from(runFills).where(eq32(runFills.runId, runId)).orderBy(desc12(runFills.createdAt), desc12(runFills.id)).get();
26542
+ const fill = db.select().from(runFills).where(eq32(runFills.runId, runId)).orderBy(desc13(runFills.createdAt), desc13(runFills.id)).get();
26399
26543
  if (!fill) return null;
26400
26544
  const { status, providers, expected, filled, createdAt, finishedAt } = formatRunFill(fill);
26401
26545
  return { status, providers, expected, filled, createdAt, finishedAt };
@@ -26547,7 +26691,7 @@ async function measurementPortfolioReadRoutes(app) {
26547
26691
 
26548
26692
  // ../api-routes/src/visibility-report.ts
26549
26693
  import { createHash as createHash7 } from "crypto";
26550
- import { and as and26, desc as desc13, eq as eq33, gte as gte5, inArray as inArray15, isNotNull as isNotNull4, isNull as isNull8, lt as lt6, lte as lte6, or as or8 } from "drizzle-orm";
26694
+ import { and as and26, desc as desc14, eq as eq33, gte as gte5, inArray as inArray16, isNotNull as isNotNull4, isNull as isNull8, lt as lt6, lte as lte6, or as or8 } from "drizzle-orm";
26551
26695
 
26552
26696
  // ../api-routes/src/measurement-scope-options.ts
26553
26697
  function marketLinks(keys, settings) {
@@ -27366,7 +27510,7 @@ function loadVisibilitySnapshots(db, runIds) {
27366
27510
  requestedContext: querySnapshots.requestedContext,
27367
27511
  supportedContext: querySnapshots.supportedContext,
27368
27512
  createdAt: querySnapshots.createdAt
27369
- }).from(querySnapshots).where(inArray15(querySnapshots.runId, [...runIds])).all();
27513
+ }).from(querySnapshots).where(inArray16(querySnapshots.runId, [...runIds])).all();
27370
27514
  for (const row of rows) {
27371
27515
  const snapshots = byRun.get(row.runId) ?? [];
27372
27516
  snapshots.push(row);
@@ -27779,7 +27923,7 @@ function completedVisibilityRuns(db, projectId, planless, query) {
27779
27923
  return db.select().from(runs).where(and26(
27780
27924
  eq33(runs.projectId, projectId),
27781
27925
  eq33(runs.kind, RunKinds["answer-visibility"]),
27782
- inArray15(runs.status, [RunStatuses.completed, RunStatuses.partial]),
27926
+ inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
27783
27927
  notProbeRun(),
27784
27928
  planless ? isNull8(runs.measurementPlanVersionId) : isNotNull4(runs.measurementPlanVersionId),
27785
27929
  // A scoped spot check is never a whole-project sweep. It can be inspected
@@ -27788,13 +27932,13 @@ function completedVisibilityRuns(db, projectId, planless, query) {
27788
27932
  query.runId === void 0 ? void 0 : eq33(runs.id, query.runId),
27789
27933
  query.from === void 0 ? void 0 : gte5(runs.createdAt, query.from),
27790
27934
  query.to === void 0 ? void 0 : lte6(runs.createdAt, query.to)
27791
- )).orderBy(desc13(runs.createdAt), desc13(runs.id)).limit(VISIBILITY_REPORT_MAX_RUNS).all();
27935
+ )).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(VISIBILITY_REPORT_MAX_RUNS).all();
27792
27936
  }
27793
27937
  function previousEligibleVisibilityRun(db, projectId, planless, selected) {
27794
27938
  return db.select().from(runs).where(and26(
27795
27939
  eq33(runs.projectId, projectId),
27796
27940
  eq33(runs.kind, RunKinds["answer-visibility"]),
27797
- inArray15(runs.status, [RunStatuses.completed, RunStatuses.partial]),
27941
+ inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
27798
27942
  notProbeRun(),
27799
27943
  planless ? isNull8(runs.measurementPlanVersionId) : isNotNull4(runs.measurementPlanVersionId),
27800
27944
  isNull8(runs.measurementScope),
@@ -27802,7 +27946,7 @@ function previousEligibleVisibilityRun(db, projectId, planless, selected) {
27802
27946
  lt6(runs.createdAt, selected.createdAt),
27803
27947
  and26(eq33(runs.createdAt, selected.createdAt), lt6(runs.id, selected.id))
27804
27948
  )
27805
- )).orderBy(desc13(runs.createdAt), desc13(runs.id)).limit(1).get();
27949
+ )).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(1).get();
27806
27950
  }
27807
27951
  function readPreviousSweep(read) {
27808
27952
  try {
@@ -27933,7 +28077,7 @@ function frozenSimpleDefinitions(db, projectId, runIds) {
27933
28077
  if (runIds.length === 0) return /* @__PURE__ */ new Map();
27934
28078
  return new Map(db.select().from(simpleMeasurementDefinitions).where(and26(
27935
28079
  eq33(simpleMeasurementDefinitions.projectId, projectId),
27936
- inArray15(simpleMeasurementDefinitions.runId, [...runIds])
28080
+ inArray16(simpleMeasurementDefinitions.runId, [...runIds])
27937
28081
  )).all().map((row) => [row.runId, row.definition]));
27938
28082
  }
27939
28083
  function simpleRunInput(db, project, run, definition, includeEvidence) {
@@ -28002,7 +28146,7 @@ function readVisibilityComparisonRuns(db, projectId, since, until, includeEviden
28002
28146
  const sourceRuns = db.select().from(runs).where(and26(
28003
28147
  eq33(runs.projectId, projectId),
28004
28148
  eq33(runs.kind, RunKinds["answer-visibility"]),
28005
- inArray15(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28149
+ inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28006
28150
  notProbeRun(),
28007
28151
  isNotNull4(runs.measurementPlanVersionId),
28008
28152
  isNull8(runs.measurementScope),
@@ -28032,7 +28176,7 @@ function readVisibilityComparisonRuns(db, projectId, since, until, includeEviden
28032
28176
 
28033
28177
  // ../api-routes/src/query-tracking.ts
28034
28178
  import crypto21 from "crypto";
28035
- import { and as and27, desc as desc14, eq as eq34, inArray as inArray16, isNotNull as isNotNull5, isNull as isNull9, ne as ne6 } from "drizzle-orm";
28179
+ import { and as and27, desc as desc15, eq as eq34, inArray as inArray17, isNotNull as isNotNull5, isNull as isNull9, ne as ne6 } from "drizzle-orm";
28036
28180
  var SOURCE_LIMIT = 100;
28037
28181
  var MAX_REVIEW_AGE_MS = 15 * 60 * 1e3;
28038
28182
  var MAX_REVIEW_FUTURE_SKEW_MS = 60 * 1e3;
@@ -28218,11 +28362,11 @@ function simpleMeasuredAtByQuery(db, project, queryRows2, opts) {
28218
28362
  }).from(runs).where(and27(
28219
28363
  eq34(runs.projectId, project.id),
28220
28364
  eq34(runs.kind, RunKinds["answer-visibility"]),
28221
- inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28365
+ inArray17(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28222
28366
  ne6(runs.trigger, RunTriggers.probe),
28223
28367
  isNull9(runs.measurementScope),
28224
28368
  isNull9(runs.measurementPlanVersionId)
28225
- )).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(SOURCE_LIMIT).all();
28369
+ )).orderBy(desc15(runs.createdAt), desc15(runs.id)).limit(SOURCE_LIMIT).all();
28226
28370
  if (eligibleRuns.length === 0) return /* @__PURE__ */ new Map();
28227
28371
  const frozenByRun = /* @__PURE__ */ new Map();
28228
28372
  for (const row of db.select({
@@ -28230,7 +28374,7 @@ function simpleMeasuredAtByQuery(db, project, queryRows2, opts) {
28230
28374
  definition: simpleMeasurementDefinitions.definition
28231
28375
  }).from(simpleMeasurementDefinitions).where(and27(
28232
28376
  eq34(simpleMeasurementDefinitions.projectId, project.id),
28233
- inArray16(simpleMeasurementDefinitions.runId, eligibleRuns.map((run) => run.id))
28377
+ inArray17(simpleMeasurementDefinitions.runId, eligibleRuns.map((run) => run.id))
28234
28378
  )).all()) {
28235
28379
  const parsed = simpleMeasurementDefinitionSchema.safeParse(row.definition);
28236
28380
  if (parsed.success) frozenByRun.set(row.runId, parsed.data);
@@ -28242,7 +28386,7 @@ function simpleMeasuredAtByQuery(db, project, queryRows2, opts) {
28242
28386
  queryId: querySnapshots.queryId,
28243
28387
  queryText: querySnapshots.queryText,
28244
28388
  provider: querySnapshots.provider
28245
- }).from(querySnapshots).where(inArray16(querySnapshots.runId, [...frozenByRun.keys()])).all()) {
28389
+ }).from(querySnapshots).where(inArray17(querySnapshots.runId, [...frozenByRun.keys()])).all()) {
28246
28390
  if (!snapshot.queryId) continue;
28247
28391
  const byQuery = snapshotsByRunQuery.get(snapshot.runId) ?? /* @__PURE__ */ new Map();
28248
28392
  const rows = byQuery.get(snapshot.queryId) ?? [];
@@ -28340,11 +28484,11 @@ function measuredAtByQuery(db, state, opts) {
28340
28484
  const eligibleRuns = db.select().from(runs).where(and27(
28341
28485
  eq34(runs.projectId, project.id),
28342
28486
  eq34(runs.kind, RunKinds["answer-visibility"]),
28343
- inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28487
+ inArray17(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28344
28488
  ne6(runs.trigger, RunTriggers.probe),
28345
28489
  isNull9(runs.measurementScope),
28346
28490
  isNotNull5(runs.measurementPlanVersionId)
28347
- )).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(SOURCE_LIMIT).all();
28491
+ )).orderBy(desc15(runs.createdAt), desc15(runs.id)).limit(SOURCE_LIMIT).all();
28348
28492
  if (eligibleRuns.length === 0) return /* @__PURE__ */ new Map();
28349
28493
  const versionIds = unique2(eligibleRuns.flatMap((run) => run.measurementPlanVersionId ? [run.measurementPlanVersionId] : []));
28350
28494
  const versionPlans = new Map(db.select({
@@ -28353,7 +28497,7 @@ function measuredAtByQuery(db, state, opts) {
28353
28497
  canonicalJson: measurementPlanVersions.canonicalJson
28354
28498
  }).from(measurementPlanVersions).where(and27(
28355
28499
  eq34(measurementPlanVersions.projectId, project.id),
28356
- inArray16(measurementPlanVersions.id, versionIds)
28500
+ inArray17(measurementPlanVersions.id, versionIds)
28357
28501
  )).all().flatMap((row) => {
28358
28502
  const parsed = parseStoredMeasurementPlanAnyVersion(row.canonicalJson);
28359
28503
  return parsed.schemaVersion === 2 ? [[row.id, { revision: row.revision, plan: parsed }]] : [];
@@ -28385,7 +28529,7 @@ function measuredAtByQuery(db, state, opts) {
28385
28529
  measurementExecutionId: querySnapshots.measurementExecutionId,
28386
28530
  requestedContext: querySnapshots.requestedContext,
28387
28531
  supportedContext: querySnapshots.supportedContext
28388
- }).from(querySnapshots).where(inArray16(querySnapshots.runId, eligibleRuns.map((run) => run.id))).all();
28532
+ }).from(querySnapshots).where(inArray17(querySnapshots.runId, eligibleRuns.map((run) => run.id))).all();
28389
28533
  for (const snapshot of snapshotRows) {
28390
28534
  const snapshots = snapshotsByRun.get(snapshot.runId) ?? [];
28391
28535
  snapshots.push(snapshot);
@@ -28533,13 +28677,13 @@ function savedSources(db, projectId) {
28533
28677
  researchRunQueryId: researchRunQueries.id,
28534
28678
  queryText: researchRunQueries.queryText,
28535
28679
  createdAt: researchRunQueries.createdAt
28536
- }).from(researchRunQueries).innerJoin(researchRuns, eq34(researchRunQueries.researchRunId, researchRuns.id)).where(eq34(researchRuns.projectId, projectId)).orderBy(desc14(researchRunQueries.createdAt)).limit(SOURCE_LIMIT).all().filter((row) => row.queryText.trim().length > 0);
28680
+ }).from(researchRunQueries).innerJoin(researchRuns, eq34(researchRunQueries.researchRunId, researchRuns.id)).where(eq34(researchRuns.projectId, projectId)).orderBy(desc15(researchRunQueries.createdAt)).limit(SOURCE_LIMIT).all().filter((row) => row.queryText.trim().length > 0);
28537
28681
  const discovery = db.select({
28538
28682
  discoverySessionId: discoverySessions.id,
28539
28683
  discoveryProbeId: discoveryProbes.id,
28540
28684
  queryText: discoveryProbes.query,
28541
28685
  createdAt: discoveryProbes.createdAt
28542
- }).from(discoveryProbes).innerJoin(discoverySessions, eq34(discoveryProbes.sessionId, discoverySessions.id)).where(eq34(discoverySessions.projectId, projectId)).orderBy(desc14(discoveryProbes.createdAt)).limit(SOURCE_LIMIT).all().filter((row) => row.queryText.trim().length > 0);
28686
+ }).from(discoveryProbes).innerJoin(discoverySessions, eq34(discoveryProbes.sessionId, discoverySessions.id)).where(eq34(discoverySessions.projectId, projectId)).orderBy(desc15(discoveryProbes.createdAt)).limit(SOURCE_LIMIT).all().filter((row) => row.queryText.trim().length > 0);
28543
28687
  return { research, discovery };
28544
28688
  }
28545
28689
  function workspaceDto(db, state, opts) {
@@ -29394,7 +29538,7 @@ function writeAdvancedCandidate(tx, candidate, request, now) {
29394
29538
  const removed = current.filter((row) => !candidate.queryRows.has(row.id));
29395
29539
  if (removed.length > 0) {
29396
29540
  preserveSnapshotQueryText(tx, candidate.state.project.id, removed.map((row) => row.id));
29397
- tx.delete(queries).where(inArray16(queries.id, removed.map((row) => row.id))).run();
29541
+ tx.delete(queries).where(inArray17(queries.id, removed.map((row) => row.id))).run();
29398
29542
  }
29399
29543
  for (const row of candidate.queryRows.values()) {
29400
29544
  const previous = currentById.get(row.id);
@@ -29413,7 +29557,7 @@ function writeAdvancedCandidate(tx, candidate, request, now) {
29413
29557
  if (!candidate.planChanged) return active;
29414
29558
  const plan = candidate.plan;
29415
29559
  const canonicalJson3 = canonicalMeasurementPlanV2Json(plan);
29416
- const latest = tx.select().from(measurementPlanVersions).where(eq34(measurementPlanVersions.projectId, candidate.state.project.id)).orderBy(desc14(measurementPlanVersions.revision)).get();
29560
+ const latest = tx.select().from(measurementPlanVersions).where(eq34(measurementPlanVersions.projectId, candidate.state.project.id)).orderBy(desc15(measurementPlanVersions.revision)).get();
29417
29561
  const revision = (latest?.revision ?? 0) + 1;
29418
29562
  const versionId = crypto21.randomUUID();
29419
29563
  tx.insert(measurementPlanVersions).values({
@@ -30222,7 +30366,7 @@ function aliasArraysEqual2(a, b) {
30222
30366
  }
30223
30367
 
30224
30368
  // ../api-routes/src/history.ts
30225
- import { and as and29, asc as asc5, count, desc as desc15, eq as eq36, gte as gte6, inArray as inArray17, like as like2, ne as ne7, or as or9 } from "drizzle-orm";
30369
+ import { and as and29, asc as asc5, count, desc as desc16, eq as eq36, gte as gte6, inArray as inArray18, like as like2, ne as ne7, or as or9 } from "drizzle-orm";
30226
30370
 
30227
30371
  // ../api-routes/src/notification-redaction.ts
30228
30372
  var REDACTED_URL = {
@@ -30274,27 +30418,27 @@ async function historyRoutes(app) {
30274
30418
  if (!parsed.success) throw validationError("Invalid history cleanup request", { issues: parsed.error.issues });
30275
30419
  const input = parsed.data;
30276
30420
  return app.db.transaction((tx) => {
30277
- const active = tx.select({ id: runs.id }).from(runs).where(and29(eq36(runs.projectId, project.id), eq36(runs.kind, RunKinds["answer-visibility"]), inArray17(runs.status, ["queued", "running"]))).get();
30278
- const activeResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray17(researchRuns.status, ["queued", "running"]))).get();
30421
+ const active = tx.select({ id: runs.id }).from(runs).where(and29(eq36(runs.projectId, project.id), eq36(runs.kind, RunKinds["answer-visibility"]), inArray18(runs.status, ["queued", "running"]))).get();
30422
+ const activeResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray18(researchRuns.status, ["queued", "running"]))).get();
30279
30423
  if (active || activeResearch) throw runInProgress(project.name, active ? "answer-visibility" : "research", (active ?? activeResearch).id);
30280
- const activeFill = tx.select({ id: runFills.id, runId: runFills.runId }).from(runFills).where(and29(eq36(runFills.projectId, project.id), inArray17(runFills.status, ["queued", "running"]))).get();
30424
+ const activeFill = tx.select({ id: runFills.id, runId: runFills.runId }).from(runFills).where(and29(eq36(runFills.projectId, project.id), inArray18(runFills.status, ["queued", "running"]))).get();
30281
30425
  if (activeFill) throw runFillInProgress(activeFill.runId, activeFill.id);
30282
- const selectedRuns = tx.select({ id: runs.id, kind: runs.kind }).from(runs).where(and29(eq36(runs.projectId, project.id), inArray17(runs.id, input.runIds))).all();
30283
- const selectedResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray17(researchRuns.id, input.researchRunIds))).all();
30426
+ const selectedRuns = tx.select({ id: runs.id, kind: runs.kind }).from(runs).where(and29(eq36(runs.projectId, project.id), inArray18(runs.id, input.runIds))).all();
30427
+ const selectedResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray18(researchRuns.id, input.researchRunIds))).all();
30284
30428
  if (selectedRuns.length !== input.runIds.length || selectedResearch.length !== input.researchRunIds.length) throw notFound("Selected saved run in project", project.name);
30285
30429
  if (selectedRuns.some((run) => run.kind !== RunKinds["answer-visibility"])) throw validationError("Only answer-visibility runs and research batches can be cleared. Site Health and integration runs are preserved.");
30286
30430
  const result = {
30287
30431
  dryRun: !input.confirm,
30288
30432
  runIds: input.runIds,
30289
30433
  researchRunIds: input.researchRunIds,
30290
- querySnapshots: tx.select({ value: count() }).from(querySnapshots).where(inArray17(querySnapshots.runId, input.runIds)).get().value,
30291
- researchQueries: tx.select({ value: count() }).from(researchRunQueries).where(inArray17(researchRunQueries.researchRunId, input.researchRunIds)).get().value,
30292
- insights: tx.select({ value: count() }).from(insights).where(inArray17(insights.runId, input.runIds)).get().value,
30293
- healthSnapshots: tx.select({ value: count() }).from(healthSnapshots).where(inArray17(healthSnapshots.runId, input.runIds)).get().value
30434
+ querySnapshots: tx.select({ value: count() }).from(querySnapshots).where(inArray18(querySnapshots.runId, input.runIds)).get().value,
30435
+ researchQueries: tx.select({ value: count() }).from(researchRunQueries).where(inArray18(researchRunQueries.researchRunId, input.researchRunIds)).get().value,
30436
+ insights: tx.select({ value: count() }).from(insights).where(inArray18(insights.runId, input.runIds)).get().value,
30437
+ healthSnapshots: tx.select({ value: count() }).from(healthSnapshots).where(inArray18(healthSnapshots.runId, input.runIds)).get().value
30294
30438
  };
30295
30439
  if (input.confirm) {
30296
- tx.delete(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray17(researchRuns.id, input.researchRunIds))).run();
30297
- tx.delete(runs).where(and29(eq36(runs.projectId, project.id), inArray17(runs.id, input.runIds))).run();
30440
+ tx.delete(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray18(researchRuns.id, input.researchRunIds))).run();
30441
+ tx.delete(runs).where(and29(eq36(runs.projectId, project.id), inArray18(runs.id, input.runIds))).run();
30298
30442
  writeAuditLog(tx, { projectId: project.id, actor: "api", action: "results.cleared", entityType: "project", entityId: project.id, diff: result });
30299
30443
  }
30300
30444
  return result;
@@ -30305,7 +30449,7 @@ async function historyRoutes(app) {
30305
30449
  const filters = [eq36(auditLog.projectId, project.id)];
30306
30450
  if (request.operatorAccess !== true) filters.push(ne7(auditLog.entityType, "telemetry"));
30307
30451
  addAuditHistoryFilters(filters, request.query);
30308
- const rows = app.db.select().from(auditLog).where(and29(...filters)).orderBy(desc15(auditLog.createdAt), desc15(auditLog.id)).limit(parseBoundedInt(request.query.limit, 100, 500)).offset(parseBoundedInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER)).all();
30452
+ const rows = app.db.select().from(auditLog).where(and29(...filters)).orderBy(desc16(auditLog.createdAt), desc16(auditLog.id)).limit(parseBoundedInt(request.query.limit, 100, 500)).offset(parseBoundedInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER)).all();
30309
30453
  return reply.send(rows.map(formatAuditEntry));
30310
30454
  });
30311
30455
  app.get("/history", async (request, reply) => {
@@ -30313,7 +30457,7 @@ async function historyRoutes(app) {
30313
30457
  const filters = scopedProjectId ? [eq36(auditLog.projectId, scopedProjectId)] : [];
30314
30458
  if (request.operatorAccess !== true) filters.push(ne7(auditLog.entityType, "telemetry"));
30315
30459
  addAuditHistoryFilters(filters, request.query);
30316
- const rows = app.db.select().from(auditLog).where(filters.length > 0 ? and29(...filters) : void 0).orderBy(desc15(auditLog.createdAt), desc15(auditLog.id)).limit(parseBoundedInt(request.query.limit, 100, 500)).offset(parseBoundedInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER)).all();
30460
+ const rows = app.db.select().from(auditLog).where(filters.length > 0 ? and29(...filters) : void 0).orderBy(desc16(auditLog.createdAt), desc16(auditLog.id)).limit(parseBoundedInt(request.query.limit, 100, 500)).offset(parseBoundedInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER)).all();
30317
30461
  return reply.send(rows.map(formatAuditEntry));
30318
30462
  });
30319
30463
  app.get("/projects/:name/snapshots", async (request, reply) => {
@@ -30346,7 +30490,7 @@ async function historyRoutes(app) {
30346
30490
  location: querySnapshots.location,
30347
30491
  rawResponse: querySnapshots.rawResponse,
30348
30492
  createdAt: querySnapshots.createdAt
30349
- }).from(querySnapshots).leftJoin(queries, eq36(querySnapshots.queryId, queries.id)).where(inArray17(querySnapshots.runId, projectRuns.map((r) => r.id))).orderBy(desc15(querySnapshots.createdAt)).all();
30493
+ }).from(querySnapshots).leftJoin(queries, eq36(querySnapshots.queryId, queries.id)).where(inArray18(querySnapshots.runId, projectRuns.map((r) => r.id))).orderBy(desc16(querySnapshots.createdAt)).all();
30350
30494
  const locationFilter = request.query.location;
30351
30495
  const filtered = locationFilter !== void 0 ? allSnapshots.filter((s) => s.location === (locationFilter || null)) : allSnapshots;
30352
30496
  const total = filtered.length;
@@ -30401,12 +30545,12 @@ async function historyRoutes(app) {
30401
30545
  eq36(runs.kind, RunKinds["answer-visibility"])
30402
30546
  );
30403
30547
  const requestedLimit = parseOptionalPositiveInt(request.query.limit, 100);
30404
- const projectRuns = requestedLimit == null ? app.db.select().from(runs).where(runKindFilter).orderBy(asc5(runs.createdAt)).all() : app.db.select().from(runs).where(runKindFilter).orderBy(desc15(runs.createdAt)).limit(requestedLimit).all().reverse();
30548
+ const projectRuns = requestedLimit == null ? app.db.select().from(runs).where(runKindFilter).orderBy(asc5(runs.createdAt)).all() : app.db.select().from(runs).where(runKindFilter).orderBy(desc16(runs.createdAt)).limit(requestedLimit).all().reverse();
30405
30549
  if (projectRuns.length === 0 || projectQueries.length === 0) {
30406
30550
  return reply.send([]);
30407
30551
  }
30408
30552
  const runIds = new Set(projectRuns.map((r) => r.id));
30409
- const rawSnapshots = app.db.select().from(querySnapshots).where(inArray17(querySnapshots.runId, [...runIds])).all();
30553
+ const rawSnapshots = app.db.select().from(querySnapshots).where(inArray18(querySnapshots.runId, [...runIds])).all();
30410
30554
  const timelineLocationFilter = request.query.location;
30411
30555
  const filteredSnapshots = timelineLocationFilter !== void 0 ? rawSnapshots.filter((s) => s.location === (timelineLocationFilter || null)) : rawSnapshots;
30412
30556
  const allSnapshots = filteredSnapshots.map((snapshot) => ({
@@ -30527,7 +30671,7 @@ async function historyRoutes(app) {
30527
30671
  throw validationError("Both run1 and run2 query params are required");
30528
30672
  }
30529
30673
  const requestedRunIds = [.../* @__PURE__ */ new Set([run1, run2])];
30530
- const runRows = app.db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(inArray17(runs.id, requestedRunIds)).all();
30674
+ const runRows = app.db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(inArray18(runs.id, requestedRunIds)).all();
30531
30675
  const runsById = new Map(runRows.map((row) => [row.id, row]));
30532
30676
  for (const runId of requestedRunIds) {
30533
30677
  const run = runsById.get(runId);
@@ -30632,7 +30776,7 @@ function parseOptionalPositiveInt(value, max2) {
30632
30776
  }
30633
30777
 
30634
30778
  // ../api-routes/src/analytics.ts
30635
- import { and as and30, desc as desc16, eq as eq37, gte as gte7, inArray as inArray18, lt as lt7 } from "drizzle-orm";
30779
+ import { and as and30, desc as desc17, eq as eq37, gte as gte7, inArray as inArray19, lt as lt7 } from "drizzle-orm";
30636
30780
 
30637
30781
  // ../api-routes/src/analytics-model-attribution.ts
30638
30782
  function logicalSweeps(observations) {
@@ -30728,10 +30872,10 @@ async function analyticsRoutes(app) {
30728
30872
  const projectRuns = app.db.select().from(runs).where(and30(
30729
30873
  eq37(runs.projectId, project.id),
30730
30874
  eq37(runs.kind, RunKinds["answer-visibility"]),
30731
- inArray18(runs.status, [RunStatuses.completed, RunStatuses.partial]),
30875
+ inArray19(runs.status, [RunStatuses.completed, RunStatuses.partial]),
30732
30876
  notProbeRun(),
30733
30877
  cutoff ? gte7(runs.createdAt, cutoff) : void 0
30734
- )).orderBy(desc16(runs.createdAt)).all().filter((r) => measuredWhole(app.db, r)).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
30878
+ )).orderBy(desc17(runs.createdAt)).all().filter((r) => measuredWhole(app.db, r)).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
30735
30879
  if (projectRuns.length === 0) {
30736
30880
  return reply.send({
30737
30881
  window,
@@ -30773,7 +30917,7 @@ async function analyticsRoutes(app) {
30773
30917
  citationState: querySnapshots.citationState,
30774
30918
  answerMentioned: querySnapshots.answerMentioned,
30775
30919
  answerText: querySnapshots.answerText
30776
- }).from(querySnapshots).where(inArray18(querySnapshots.runId, runIds)).all();
30920
+ }).from(querySnapshots).where(inArray19(querySnapshots.runId, runIds)).all();
30777
30921
  const rawSnapshots = referenceBasket ? loadedSnapshots.filter(
30778
30922
  (s) => s.queryId !== null || s.queryText !== null && referenceBasket.has(normalizeQueryText(s.queryText))
30779
30923
  ) : filterTrackedSnapshots(loadedSnapshots);
@@ -30823,11 +30967,11 @@ async function analyticsRoutes(app) {
30823
30967
  const anchorRunPredicate = and30(
30824
30968
  eq37(runs.projectId, project.id),
30825
30969
  eq37(runs.kind, RunKinds["answer-visibility"]),
30826
- inArray18(runs.status, [RunStatuses.completed, RunStatuses.partial]),
30970
+ inArray19(runs.status, [RunStatuses.completed, RunStatuses.partial]),
30827
30971
  notProbeRun(),
30828
30972
  lt7(runs.createdAt, cutoff)
30829
30973
  );
30830
- const anchorSweepTimes = app.db.selectDistinct({ createdAt: runs.createdAt }).from(runs).where(anchorRunPredicate).orderBy(desc16(runs.createdAt)).limit(ANCHOR_SWEEP_SCAN_LIMIT + 1).all().map((row) => row.createdAt);
30974
+ const anchorSweepTimes = app.db.selectDistinct({ createdAt: runs.createdAt }).from(runs).where(anchorRunPredicate).orderBy(desc17(runs.createdAt)).limit(ANCHOR_SWEEP_SCAN_LIMIT + 1).all().map((row) => row.createdAt);
30831
30975
  const anchorScanTruncated = anchorSweepTimes.length > ANCHOR_SWEEP_SCAN_LIMIT;
30832
30976
  if (anchorScanTruncated) anchorSweepTimes.length = ANCHOR_SWEEP_SCAN_LIMIT;
30833
30977
  if (anchorSweepTimes.length > 0) {
@@ -30853,7 +30997,7 @@ async function analyticsRoutes(app) {
30853
30997
  provider: querySnapshots.provider,
30854
30998
  model: querySnapshots.model,
30855
30999
  servedModel: querySnapshots.servedModel
30856
- }).from(querySnapshots).where(inArray18(querySnapshots.runId, runIds2)).all())) {
31000
+ }).from(querySnapshots).where(inArray19(querySnapshots.runId, runIds2)).all())) {
30857
31001
  if (pending.has(snapshot.provider)) {
30858
31002
  const models = modelsByProvider.get(snapshot.provider) ?? [];
30859
31003
  models.push(snapshot.model);
@@ -30982,7 +31126,7 @@ async function analyticsRoutes(app) {
30982
31126
  const project = resolveProject(app.db, request.params.name);
30983
31127
  const window = parseWindow(request.query.window);
30984
31128
  const cutoff = windowCutoff(window);
30985
- const completedRuns = app.db.select().from(runs).where(and30(eq37(runs.projectId, project.id), eq37(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc16(runs.createdAt), desc16(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => measuredWhole(app.db, r));
31129
+ const completedRuns = app.db.select().from(runs).where(and30(eq37(runs.projectId, project.id), eq37(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc17(runs.createdAt), desc17(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => measuredWhole(app.db, r));
30986
31130
  const latestGroup = groupRunsByCreatedAt(completedRuns)[0] ?? [];
30987
31131
  const latestGroupRunIds = latestGroup.map((r) => r.id);
30988
31132
  const latestRun = pickGroupRepresentative(latestGroup);
@@ -31005,7 +31149,7 @@ async function analyticsRoutes(app) {
31005
31149
  citationState: querySnapshots.citationState,
31006
31150
  answerMentioned: querySnapshots.answerMentioned,
31007
31151
  answerText: querySnapshots.answerText
31008
- }).from(querySnapshots).where(inArray18(querySnapshots.runId, windowRunIds)).all());
31152
+ }).from(querySnapshots).where(inArray19(querySnapshots.runId, windowRunIds)).all());
31009
31153
  for (const s of allWindowSnaps) {
31010
31154
  const timePoint = runIdToCreatedAt.get(s.runId) ?? s.runId;
31011
31155
  let entry = consistencyMap.get(s.queryId);
@@ -31026,7 +31170,7 @@ async function analyticsRoutes(app) {
31026
31170
  answerMentioned: querySnapshots.answerMentioned,
31027
31171
  answerText: querySnapshots.answerText,
31028
31172
  citedDomains: querySnapshots.citedDomains
31029
- }).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray18(querySnapshots.runId, latestGroupRunIds)).all());
31173
+ }).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray19(querySnapshots.runId, latestGroupRunIds)).all());
31030
31174
  const snapshots = rawSnapshots.map((s) => ({
31031
31175
  ...s,
31032
31176
  resolvedMentioned: resolveSnapshotAnswerMentioned(s, project)
@@ -31193,8 +31337,8 @@ async function analyticsRoutes(app) {
31193
31337
  eq37(runs.projectId, project.id),
31194
31338
  eq37(runs.kind, RunKinds["answer-visibility"]),
31195
31339
  notProbeRun(),
31196
- latestRuns ? inArray18(runs.id, latestRuns.map((run) => run.id)) : requestedRunId ? eq37(runs.id, requestedRunId) : void 0
31197
- )).orderBy(desc16(runs.createdAt), desc16(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => measuredWhole(app.db, r)).filter((r) => !cutoff || r.createdAt >= cutoff);
31340
+ latestRuns ? inArray19(runs.id, latestRuns.map((run) => run.id)) : requestedRunId ? eq37(runs.id, requestedRunId) : void 0
31341
+ )).orderBy(desc17(runs.createdAt), desc17(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => measuredWhole(app.db, r)).filter((r) => !cutoff || r.createdAt >= cutoff);
31198
31342
  if (windowRuns.length === 0) {
31199
31343
  return reply.send({
31200
31344
  ranked: buildRankedList(/* @__PURE__ */ new Map(), limit, 0, 0),
@@ -31226,7 +31370,7 @@ async function analyticsRoutes(app) {
31226
31370
  citedDomains: querySnapshots.citedDomains,
31227
31371
  citedUrls: querySnapshots.citedUrls,
31228
31372
  measurementExecutionId: querySnapshots.measurementExecutionId
31229
- }).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray18(querySnapshots.runId, windowRunIds)).all();
31373
+ }).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray19(querySnapshots.runId, windowRunIds)).all();
31230
31374
  let unclassifiedAnswers = 0;
31231
31375
  let snapshots = loadedSnapshots;
31232
31376
  if (splitByClass) {
@@ -31579,7 +31723,7 @@ function buildCategoryCounts(counts2) {
31579
31723
  }
31580
31724
 
31581
31725
  // ../api-routes/src/intelligence.ts
31582
- import { eq as eq38, desc as desc17, and as and31, inArray as inArray19, like as like3 } from "drizzle-orm";
31726
+ import { eq as eq38, desc as desc18, and as and31, inArray as inArray20, like as like3 } from "drizzle-orm";
31583
31727
  var SEVERITY_RANK = { low: 0, medium: 1, high: 2, critical: 3 };
31584
31728
  function severitiesAtOrAbove(min2) {
31585
31729
  const floor = SEVERITY_RANK[min2];
@@ -31709,7 +31853,7 @@ async function intelligenceRoutes(app) {
31709
31853
  }
31710
31854
  const severityFilter = request.query.severity?.trim();
31711
31855
  if (severityFilter) {
31712
- conditions.push(inArray19(insights.severity, severitiesAtOrAbove(severityFilter)));
31856
+ conditions.push(inArray20(insights.severity, severitiesAtOrAbove(severityFilter)));
31713
31857
  }
31714
31858
  let limit;
31715
31859
  if (request.query.limit !== void 0) {
@@ -31719,7 +31863,7 @@ async function intelligenceRoutes(app) {
31719
31863
  }
31720
31864
  limit = parsed;
31721
31865
  }
31722
- const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] : and31(...conditions)).orderBy(desc17(insights.createdAt)).all();
31866
+ const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] : and31(...conditions)).orderBy(desc18(insights.createdAt)).all();
31723
31867
  const showDismissed = request.query.dismissed === "true";
31724
31868
  let result = rows.filter((r) => showDismissed || !r.dismissed).map(mapInsightRow);
31725
31869
  if (limit !== void 0) result = result.slice(0, limit);
@@ -31747,23 +31891,23 @@ async function intelligenceRoutes(app) {
31747
31891
  const projectVisRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(and31(
31748
31892
  eq38(runs.projectId, project.id),
31749
31893
  eq38(runs.kind, RunKinds["answer-visibility"]),
31750
- inArray19(runs.status, [RunStatuses.completed, RunStatuses.partial]),
31894
+ inArray20(runs.status, [RunStatuses.completed, RunStatuses.partial]),
31751
31895
  // Health-latest is the dashboard headline; probe runs must not
31752
31896
  // displace the most recent real visibility sweep.
31753
31897
  notProbeRun()
31754
- )).orderBy(desc17(runs.createdAt), desc17(runs.id)).all();
31898
+ )).orderBy(desc18(runs.createdAt), desc18(runs.id)).all();
31755
31899
  const latestGroup = groupRunsByCreatedAt(projectVisRuns)[0] ?? [];
31756
31900
  const latestGroupRunIds = latestGroup.map((r) => r.id);
31757
31901
  if (latestGroupRunIds.length > 0) {
31758
31902
  const groupRows = app.db.select().from(healthSnapshots).where(and31(
31759
31903
  eq38(healthSnapshots.projectId, project.id),
31760
- inArray19(healthSnapshots.runId, latestGroupRunIds)
31904
+ inArray20(healthSnapshots.runId, latestGroupRunIds)
31761
31905
  )).all();
31762
31906
  if (groupRows.length > 0) {
31763
31907
  return reply.send(aggregateHealthSnapshots(project.id, groupRows));
31764
31908
  }
31765
31909
  }
31766
- const fallback = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc17(healthSnapshots.createdAt)).limit(1).get();
31910
+ const fallback = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc18(healthSnapshots.createdAt)).limit(1).get();
31767
31911
  if (!fallback) {
31768
31912
  return reply.send(emptyHealthSnapshot(project.id));
31769
31913
  }
@@ -31773,13 +31917,13 @@ async function intelligenceRoutes(app) {
31773
31917
  const project = resolveProject(app.db, request.params.name);
31774
31918
  const parsed = request.query.limit ? parseInt(request.query.limit, 10) : NaN;
31775
31919
  const limit = Number.isNaN(parsed) ? 30 : Math.min(Math.max(parsed, 1), 100);
31776
- const rows = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc17(healthSnapshots.createdAt)).limit(limit).all();
31920
+ const rows = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc18(healthSnapshots.createdAt)).limit(limit).all();
31777
31921
  return reply.send(rows.map(mapHealthRow));
31778
31922
  });
31779
31923
  }
31780
31924
 
31781
31925
  // ../api-routes/src/traffic-analytics.ts
31782
- import { and as and33, desc as desc18, eq as eq39, gte as gte8, lt as lt8, lte as lte7, ne as ne8, sql as sql13 } from "drizzle-orm";
31926
+ import { and as and33, desc as desc19, eq as eq39, gte as gte8, lt as lt8, lte as lte7, ne as ne8, sql as sql13 } from "drizzle-orm";
31783
31927
 
31784
31928
  // ../api-routes/src/ai-referral-status.ts
31785
31929
  import { and as and32, sql as sql12 } from "drizzle-orm";
@@ -31989,7 +32133,7 @@ function readTrafficActivity(db, projectId, windowDays2) {
31989
32133
  gte8(crawlerEventsHourly.tsHour, headlineStart),
31990
32134
  lte7(crawlerEventsHourly.tsHour, headlineEnd)
31991
32135
  )
31992
- ).groupBy(crawlerEventsHourly.pathNormalized).orderBy(desc18(sql13`SUM(${crawlerEventsHourly.hits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
32136
+ ).groupBy(crawlerEventsHourly.pathNormalized).orderBy(desc19(sql13`SUM(${crawlerEventsHourly.hits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
31993
32137
  const topCrawledPaths = topPathsRows.map((r) => ({
31994
32138
  path: r.path,
31995
32139
  verifiedHits: Number(r.verifiedHits),
@@ -32007,7 +32151,7 @@ function readTrafficActivity(db, projectId, windowDays2) {
32007
32151
  gte8(aiReferralEventsHourly.tsHour, headlineStart),
32008
32152
  lte7(aiReferralEventsHourly.tsHour, headlineEnd)
32009
32153
  )
32010
- ).groupBy(aiReferralEventsHourly.product).orderBy(desc18(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).all();
32154
+ ).groupBy(aiReferralEventsHourly.product).orderBy(desc19(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).all();
32011
32155
  const referralProducts = referralProductsRows.map((r) => ({
32012
32156
  product: r.product,
32013
32157
  arrivals: Number(r.arrivals),
@@ -32024,7 +32168,7 @@ function readTrafficActivity(db, projectId, windowDays2) {
32024
32168
  gte8(aiReferralEventsHourly.tsHour, headlineStart),
32025
32169
  lte7(aiReferralEventsHourly.tsHour, headlineEnd)
32026
32170
  )
32027
- ).groupBy(aiReferralEventsHourly.landingPathNormalized).orderBy(desc18(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
32171
+ ).groupBy(aiReferralEventsHourly.landingPathNormalized).orderBy(desc19(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
32028
32172
  const topReferralLandingPaths = topReferralRows.map((r) => ({
32029
32173
  path: r.path,
32030
32174
  arrivals: Number(r.arrivals),
@@ -32143,7 +32287,7 @@ async function trafficAnalyticsRoutes(app) {
32143
32287
  }
32144
32288
 
32145
32289
  // ../api-routes/src/referral-assessment.ts
32146
- import { and as and34, desc as desc19, eq as eq40, gte as gte9, lte as lte8, ne as ne9, sql as sql14 } from "drizzle-orm";
32290
+ import { and as and34, desc as desc20, eq as eq40, gte as gte9, lte as lte8, ne as ne9, sql as sql14 } from "drizzle-orm";
32147
32291
 
32148
32292
  // ../api-routes/src/ga-ai-referral-aggregation.ts
32149
32293
  function normalizeAiTrafficClass(value) {
@@ -32292,7 +32436,7 @@ function buildAiReferralDailySeries(rows) {
32292
32436
  var DEFAULT_BURST_THRESHOLD = 100;
32293
32437
  var DEFAULT_RATIO_THRESHOLD = 3;
32294
32438
  function latestGaSyncQueriedWindow(db, projectId, startDate, endDate) {
32295
- const summary3 = db.select({ start: gaTrafficSummaries.periodStart, end: gaTrafficSummaries.periodEnd, syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq40(gaTrafficSummaries.projectId, projectId)).orderBy(desc19(gaTrafficSummaries.syncedAt)).limit(1).get();
32439
+ const summary3 = db.select({ start: gaTrafficSummaries.periodStart, end: gaTrafficSummaries.periodEnd, syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq40(gaTrafficSummaries.projectId, projectId)).orderBy(desc20(gaTrafficSummaries.syncedAt)).limit(1).get();
32296
32440
  if (!summary3 || startDate < summary3.start || endDate > summary3.end) return false;
32297
32441
  const leftByAnotherSync = db.select({ id: gaAiReferrals.id }).from(gaAiReferrals).where(and34(
32298
32442
  eq40(gaAiReferrals.projectId, projectId),
@@ -32410,7 +32554,7 @@ async function referralAssessmentRoutes(app) {
32410
32554
  }
32411
32555
 
32412
32556
  // ../api-routes/src/organic-evidence.ts
32413
- import { and as and36, desc as desc20, eq as eq42, gte as gte11, lte as lte10, or as or11, sql as sql16 } from "drizzle-orm";
32557
+ import { and as and36, desc as desc21, eq as eq42, gte as gte11, lte as lte10, or as or11, sql as sql16 } from "drizzle-orm";
32414
32558
 
32415
32559
  // ../api-routes/src/ga-measurement-analysis.ts
32416
32560
  import { and as and35, eq as eq41, gte as gte10, lte as lte9, or as or10, sql as sql15 } from "drizzle-orm";
@@ -33132,7 +33276,7 @@ function buildOrganicEvidence(db, projectName, periodDays) {
33132
33276
  eq42(runs.kind, RunKinds["answer-visibility"]),
33133
33277
  eq42(runs.status, RunStatuses.completed),
33134
33278
  notProbeRun()
33135
- )).orderBy(desc20(runs.createdAt)).get();
33279
+ )).orderBy(desc21(runs.createdAt)).get();
33136
33280
  const snapshots = latest ? db.select().from(querySnapshots).where(eq42(querySnapshots.runId, latest.id)).all() : [];
33137
33281
  const completedAt = latest ? latest.finishedAt ?? latest.createdAt : null;
33138
33282
  const visibility = latest && completedAt ? {
@@ -33372,7 +33516,7 @@ async function organicEvidenceRoutes(app) {
33372
33516
  }
33373
33517
 
33374
33518
  // ../api-routes/src/citations.ts
33375
- import { and as and37, eq as eq43, inArray as inArray20 } from "drizzle-orm";
33519
+ import { and as and37, eq as eq43, inArray as inArray21 } from "drizzle-orm";
33376
33520
  async function citationRoutes(app) {
33377
33521
  app.get("/projects/:name/citations/visibility", async (request, reply) => {
33378
33522
  const project = resolveProject(app.db, request.params.name);
@@ -33396,7 +33540,7 @@ async function citationRoutes(app) {
33396
33540
  competitorOverlap: querySnapshots.competitorOverlap,
33397
33541
  answerMentioned: querySnapshots.answerMentioned,
33398
33542
  createdAt: querySnapshots.createdAt
33399
- }).from(querySnapshots).where(inArray20(querySnapshots.runId, projectRuns.map((r) => r.id))).all();
33543
+ }).from(querySnapshots).where(inArray21(querySnapshots.runId, projectRuns.map((r) => r.id))).all();
33400
33544
  if (rawSnapshots.length === 0) {
33401
33545
  return reply.send(emptyCitationVisibility("no-runs-yet"));
33402
33546
  }
@@ -33533,7 +33677,7 @@ function computeCitationVisibility(input) {
33533
33677
  }
33534
33678
 
33535
33679
  // ../api-routes/src/visibility-stats.ts
33536
- import { and as and38, desc as desc21, eq as eq44, inArray as inArray21 } from "drizzle-orm";
33680
+ import { and as and38, desc as desc22, eq as eq44, inArray as inArray22 } from "drizzle-orm";
33537
33681
 
33538
33682
  // ../api-routes/src/visibility-compare.ts
33539
33683
  var VISIBILITY_COMPARE_MIN_RUNS = 5;
@@ -34003,7 +34147,7 @@ async function visibilityStatsRoutes(app) {
34003
34147
  lastRuns = n;
34004
34148
  }
34005
34149
  const projectQueries = app.db.select({ id: queries.id, query: queries.query }).from(queries).where(eq44(queries.projectId, project.id)).all();
34006
- let projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt, status: runs.status }).from(runs).where(and38(eq44(runs.projectId, project.id), eq44(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc21(runs.createdAt)).all().filter((r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial);
34150
+ let projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt, status: runs.status }).from(runs).where(and38(eq44(runs.projectId, project.id), eq44(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc22(runs.createdAt)).all().filter((r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial);
34007
34151
  if (sinceMs !== null) projectRuns = projectRuns.filter((r) => Date.parse(r.createdAt) >= sinceMs);
34008
34152
  if (untilMs !== null) projectRuns = projectRuns.filter((r) => Date.parse(r.createdAt) <= untilMs);
34009
34153
  if (lastRuns !== null) projectRuns = projectRuns.slice(0, lastRuns);
@@ -34016,7 +34160,7 @@ async function visibilityStatsRoutes(app) {
34016
34160
  citationState: querySnapshots.citationState,
34017
34161
  answerMentioned: querySnapshots.answerMentioned,
34018
34162
  createdAt: querySnapshots.createdAt
34019
- }).from(querySnapshots).where(inArray21(querySnapshots.runId, runIds)).all() : [];
34163
+ }).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
34020
34164
  const stats = computeVisibilityStats({ queries: projectQueries, snapshots, groupBy });
34021
34165
  const queryAttribution = buildQueryAttribution(projectQueries);
34022
34166
  let shareOfVoice;
@@ -34027,7 +34171,7 @@ async function visibilityStatsRoutes(app) {
34027
34171
  queryText: querySnapshots.queryText,
34028
34172
  answerMentioned: querySnapshots.answerMentioned,
34029
34173
  answerText: querySnapshots.answerText
34030
- }).from(querySnapshots).where(inArray21(querySnapshots.runId, runIds)).all() : [];
34174
+ }).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
34031
34175
  const attributedSovSnapshots = sovSnapshots.filter((s) => resolveCurrentQuery(queryAttribution, s) !== void 0);
34032
34176
  const advanced = activeMeasurementPlan(app.db, project.id)?.plan.schemaVersion === 2;
34033
34177
  const queryClass = advanced || projectQueryClassifier(project) ? requestedQueryClass : "all";
@@ -34124,7 +34268,7 @@ function readVisibilityCompare(db, projectName, query) {
34124
34268
  answerText: querySnapshots.answerText,
34125
34269
  citedDomains: querySnapshots.citedDomains,
34126
34270
  location: querySnapshots.location
34127
- }).from(querySnapshots).where(inArray21(querySnapshots.runId, runIds)).all() : [];
34271
+ }).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
34128
34272
  return {
34129
34273
  runCount: runIds.length,
34130
34274
  snapshots: snapshots.filter((snapshot) => (providerKey2 === void 0 || normalizeText3(snapshot.provider) === providerKey2) && (locationKey2 === void 0 || (locationKey2 === "none" ? snapshot.location === null : snapshot.location !== null && normalizeText3(snapshot.location) === locationKey2)))
@@ -34235,7 +34379,7 @@ function readVisibilityContinuity(db, projectName, months) {
34235
34379
  const trackedQueries = db.select({ id: queries.id, query: queries.query }).from(queries).where(eq44(queries.projectId, project.id)).all();
34236
34380
  const loadProjectMonth = (bounds) => {
34237
34381
  const runIds = legacyCompareRunIds(db, project.id, bounds);
34238
- const rows = runIds.length > 0 && trackedQueries.length > 0 ? db.select({ queryId: querySnapshots.queryId, queryText: querySnapshots.queryText, provider: querySnapshots.provider, model: querySnapshots.model }).from(querySnapshots).where(inArray21(querySnapshots.runId, runIds)).all() : [];
34382
+ const rows = runIds.length > 0 && trackedQueries.length > 0 ? db.select({ queryId: querySnapshots.queryId, queryText: querySnapshots.queryText, provider: querySnapshots.provider, model: querySnapshots.model }).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
34239
34383
  return { runCount: runIds.length, snapshots: rows.map(bare) };
34240
34384
  };
34241
34385
  const frames = [{ frame: "project", continuity: gate(trackedQueries, loadProjectMonth(fromBounds), loadProjectMonth(toBounds)) }];
@@ -34492,7 +34636,7 @@ async function resultsExportRoutes(app) {
34492
34636
  }
34493
34637
 
34494
34638
  // ../api-routes/src/composites.ts
34495
- import { eq as eq47, and as and41, desc as desc22, sql as sql18, like as like4, or as or12, inArray as inArray22 } from "drizzle-orm";
34639
+ import { eq as eq47, and as and41, desc as desc23, sql as sql18, like as like4, or as or12, inArray as inArray23 } from "drizzle-orm";
34496
34640
 
34497
34641
  // ../api-routes/src/gsc-totals.ts
34498
34642
  import { and as and40, asc as asc7, eq as eq46, sql as sql17, max, min } from "drizzle-orm";
@@ -34768,7 +34912,7 @@ async function compositeRoutes(app, options) {
34768
34912
  const project = resolveProject(app.db, request.params.name);
34769
34913
  const filterLocation = (request.query.location ?? "").trim() || null;
34770
34914
  const sinceIso = parseSinceFilter(request.query.since);
34771
- const allRunsRaw = app.db.select().from(runs).where(and41(eq47(runs.projectId, project.id), notProbeRun())).orderBy(desc22(runs.createdAt), desc22(runs.id)).all();
34915
+ const allRunsRaw = app.db.select().from(runs).where(and41(eq47(runs.projectId, project.id), notProbeRun())).orderBy(desc23(runs.createdAt), desc23(runs.id)).all();
34772
34916
  const allRuns = allRunsRaw.filter((r) => runMatchesFilters(r, filterLocation, sinceIso));
34773
34917
  const totalRuns = allRuns.length;
34774
34918
  const visibilityRuns = allRuns.filter((r) => r.kind === RunKinds["answer-visibility"]);
@@ -34781,9 +34925,9 @@ async function compositeRoutes(app, options) {
34781
34925
  const previousVisibilityRun = pickGroupRepresentative(previousVisRunGroup);
34782
34926
  const latestRunRow = allRuns[0] ?? null;
34783
34927
  const latestRun = latestRunRow ? { totalRuns, run: summarizeRun(latestRunRow) } : { totalRuns: 0, run: null };
34784
- const healthRow = app.db.select().from(healthSnapshots).where(eq47(healthSnapshots.projectId, project.id)).orderBy(desc22(healthSnapshots.createdAt)).limit(1).get();
34928
+ const healthRow = app.db.select().from(healthSnapshots).where(eq47(healthSnapshots.projectId, project.id)).orderBy(desc23(healthSnapshots.createdAt)).limit(1).get();
34785
34929
  const health = healthRow ? mapHealthRow2(healthRow) : null;
34786
- const insightRows = app.db.select().from(insights).where(eq47(insights.projectId, project.id)).orderBy(desc22(insights.createdAt)).all();
34930
+ const insightRows = app.db.select().from(insights).where(eq47(insights.projectId, project.id)).orderBy(desc23(insights.createdAt)).all();
34787
34931
  const topInsights = insightRows.filter((row) => !row.dismissed).slice(0, TOP_INSIGHT_LIMIT).map(mapInsightRow2);
34788
34932
  const sparklineRunIds = visibilityRuns.slice(0, DEFAULT_RUN_HISTORY_LIMIT).map((r) => r.id);
34789
34933
  const snapshotRunIds = new Set(sparklineRunIds);
@@ -34955,7 +35099,7 @@ async function compositeRoutes(app, options) {
34955
35099
  like4(queries.query, pattern)
34956
35100
  )
34957
35101
  )
34958
- ).orderBy(desc22(querySnapshots.createdAt)).limit(limit + 1).all());
35102
+ ).orderBy(desc23(querySnapshots.createdAt)).limit(limit + 1).all());
34959
35103
  const insightMatches = app.db.select().from(insights).where(
34960
35104
  and41(
34961
35105
  eq47(insights.projectId, project.id),
@@ -34966,7 +35110,7 @@ async function compositeRoutes(app, options) {
34966
35110
  sql18`${insights.cause} LIKE ${pattern} ESCAPE '\\'`
34967
35111
  )
34968
35112
  )
34969
- ).orderBy(desc22(insights.createdAt)).limit(limit + 1).all();
35113
+ ).orderBy(desc23(insights.createdAt)).limit(limit + 1).all();
34970
35114
  const hits = [];
34971
35115
  for (const row of snapshotMatches) {
34972
35116
  hits.push(buildSnapshotHit(row, rawQuery));
@@ -35038,7 +35182,7 @@ function loadSnapshotsByRunIds(app, runIds, queryIdByText) {
35038
35182
  rawResponse: querySnapshots.rawResponse,
35039
35183
  competitorOverlap: querySnapshots.competitorOverlap,
35040
35184
  citedDomains: querySnapshots.citedDomains
35041
- }).from(querySnapshots).where(inArray22(querySnapshots.runId, [...runIds])).all();
35185
+ }).from(querySnapshots).where(inArray23(querySnapshots.runId, [...runIds])).all();
35042
35186
  for (const row of rows) {
35043
35187
  const queryText = row.queryText?.trim() || null;
35044
35188
  let queryId;
@@ -35190,8 +35334,8 @@ function buildIndexCoverageScore(app, projectId) {
35190
35334
  tooltip,
35191
35335
  trend: []
35192
35336
  };
35193
- const gscRow = app.db.select().from(gscCoverageSnapshots).where(eq47(gscCoverageSnapshots.projectId, projectId)).orderBy(desc22(gscCoverageSnapshots.date)).limit(1).get();
35194
- const bingRow = app.db.select().from(bingCoverageSnapshots).where(eq47(bingCoverageSnapshots.projectId, projectId)).orderBy(desc22(bingCoverageSnapshots.date)).limit(1).get();
35337
+ const gscRow = app.db.select().from(gscCoverageSnapshots).where(eq47(gscCoverageSnapshots.projectId, projectId)).orderBy(desc23(gscCoverageSnapshots.date)).limit(1).get();
35338
+ const bingRow = app.db.select().from(bingCoverageSnapshots).where(eq47(bingCoverageSnapshots.projectId, projectId)).orderBy(desc23(bingCoverageSnapshots.date)).limit(1).get();
35195
35339
  const chosen = pickIndexCoverageRow(gscRow, bingRow);
35196
35340
  if (!chosen) return empty;
35197
35341
  const total = chosen.indexed + chosen.notIndexed;
@@ -35217,7 +35361,7 @@ function countGoogleDeindexedUrls(app, projectId) {
35217
35361
  url: gscUrlInspections.url,
35218
35362
  indexingState: gscUrlInspections.indexingState,
35219
35363
  inspectedAt: gscUrlInspections.inspectedAt
35220
- }).from(gscUrlInspections).where(eq47(gscUrlInspections.projectId, projectId)).orderBy(desc22(gscUrlInspections.inspectedAt)).all();
35364
+ }).from(gscUrlInspections).where(eq47(gscUrlInspections.projectId, projectId)).orderBy(desc23(gscUrlInspections.inspectedAt)).all();
35221
35365
  if (rows.length === 0) return 0;
35222
35366
  const canonicalUrl = (url) => url.replace(/^http:\/\//, "https://");
35223
35367
  const historyByUrl = /* @__PURE__ */ new Map();
@@ -35473,10 +35617,10 @@ function makeSnippet(text2, query) {
35473
35617
 
35474
35618
  // ../api-routes/src/content.ts
35475
35619
  import crypto24 from "crypto";
35476
- import { and as and43, desc as desc24, eq as eq49 } from "drizzle-orm";
35620
+ import { and as and43, desc as desc25, eq as eq49 } from "drizzle-orm";
35477
35621
 
35478
35622
  // ../api-routes/src/content-data.ts
35479
- import { and as and42, eq as eq48, desc as desc23, gte as gte13, inArray as inArray23, lte as lte12 } from "drizzle-orm";
35623
+ import { and as and42, eq as eq48, desc as desc24, gte as gte13, inArray as inArray24, lte as lte12 } from "drizzle-orm";
35480
35624
  var RECENT_RUNS_WINDOW = 5;
35481
35625
  function loadOrchestratorInput(db, project, locationFilter = void 0, gscWindowDays = DEFAULT_CONTENT_GSC_WINDOW_DAYS) {
35482
35626
  const projectId = project.id;
@@ -35616,12 +35760,12 @@ function listRecentAnswerVisibilityRunIds(db, projectId, limit, locationFilter)
35616
35760
  // Queued/running/failed/cancelled runs may have partial or no
35617
35761
  // snapshots; including them risks pointing latestRunId at a run with
35618
35762
  // no usable evidence.
35619
- inArray23(runs.status, [RunStatuses.completed, RunStatuses.partial]),
35763
+ inArray24(runs.status, [RunStatuses.completed, RunStatuses.partial]),
35620
35764
  // Probe runs are operator/agent test runs; they must not poison the
35621
35765
  // recent-runs window the content engine uses to recommend actions.
35622
35766
  notProbeRun()
35623
35767
  )
35624
- ).orderBy(desc23(runs.createdAt)).all();
35768
+ ).orderBy(desc24(runs.createdAt)).all();
35625
35769
  const filtered = locationFilter === void 0 ? rows : rows.filter((r) => (r.location ?? null) === locationFilter);
35626
35770
  return filtered.slice(0, limit).map((r) => r.id);
35627
35771
  }
@@ -35656,7 +35800,7 @@ function buildGaTrafficByPage(db, projectId, window) {
35656
35800
  return map;
35657
35801
  }
35658
35802
  function resolveContentGaWindow(db, projectId, windowDays2) {
35659
- const latest = db.select({ date: gaTrafficSnapshots.date }).from(gaTrafficSnapshots).where(eq48(gaTrafficSnapshots.projectId, projectId)).orderBy(desc23(gaTrafficSnapshots.date)).limit(1).get();
35803
+ const latest = db.select({ date: gaTrafficSnapshots.date }).from(gaTrafficSnapshots).where(eq48(gaTrafficSnapshots.projectId, projectId)).orderBy(desc24(gaTrafficSnapshots.date)).limit(1).get();
35660
35804
  if (!latest?.date) return null;
35661
35805
  const end = /* @__PURE__ */ new Date(`${latest.date}T00:00:00Z`);
35662
35806
  end.setUTCDate(end.getUTCDate() - (Math.max(1, windowDays2) - 1));
@@ -35684,7 +35828,7 @@ function buildCandidateQueries(opts) {
35684
35828
  const queryRows2 = opts.db.select({ id: queries.id, text: queries.query }).from(queries).where(eq48(queries.projectId, opts.projectId)).all();
35685
35829
  const queryIdByText = new Map(queryRows2.map((r) => [r.text, r.id]));
35686
35830
  const candidateQueryIds = opts.candidateQueryStrings.map((q) => queryIdByText.get(q)).filter((id) => Boolean(id));
35687
- const snapshotRows = filterTrackedSnapshots(opts.db.select().from(querySnapshots).where(inArray23(querySnapshots.runId, opts.recentRunIds)).all()).filter((r) => candidateQueryIds.includes(r.queryId));
35831
+ const snapshotRows = filterTrackedSnapshots(opts.db.select().from(querySnapshots).where(inArray24(querySnapshots.runId, opts.recentRunIds)).all()).filter((r) => candidateQueryIds.includes(r.queryId));
35688
35832
  const snapshotsByQuery = /* @__PURE__ */ new Map();
35689
35833
  for (const row of snapshotRows) {
35690
35834
  const list = snapshotsByQuery.get(row.queryId) ?? [];
@@ -36084,7 +36228,7 @@ async function contentRoutes(app, opts = {}) {
36084
36228
  const row = app.db.select().from(recommendationExplanations).where(and43(
36085
36229
  eq49(recommendationExplanations.projectId, project.id),
36086
36230
  eq49(recommendationExplanations.targetRef, request.params.targetRef)
36087
- )).orderBy(desc24(recommendationExplanations.generatedAt)).limit(1).get();
36231
+ )).orderBy(desc25(recommendationExplanations.generatedAt)).limit(1).get();
36088
36232
  if (!row) {
36089
36233
  return reply.status(404).send({ error: { code: "NOT_FOUND", message: "No cached explanation for this targetRef." } });
36090
36234
  }
@@ -36112,7 +36256,7 @@ async function contentRoutes(app, opts = {}) {
36112
36256
  const cached = app.db.select().from(recommendationExplanations).where(and43(
36113
36257
  eq49(recommendationExplanations.projectId, project.id),
36114
36258
  eq49(recommendationExplanations.targetRef, targetRef)
36115
- )).orderBy(desc24(recommendationExplanations.generatedAt)).limit(1).get();
36259
+ )).orderBy(desc25(recommendationExplanations.generatedAt)).limit(1).get();
36116
36260
  if (cached) return reply.send(formatExplanationRow(cached));
36117
36261
  }
36118
36262
  const result = await explainer({
@@ -36242,7 +36386,7 @@ async function contentRoutes(app, opts = {}) {
36242
36386
  });
36243
36387
  app.get("/projects/:name/content/domain-classifications", async (request) => {
36244
36388
  const project = resolveProject(app.db, request.params.name);
36245
- const rows = app.db.select().from(domainClassifications).where(eq49(domainClassifications.projectId, project.id)).orderBy(desc24(domainClassifications.hits)).all();
36389
+ const rows = app.db.select().from(domainClassifications).where(eq49(domainClassifications.projectId, project.id)).orderBy(desc25(domainClassifications.hits)).all();
36246
36390
  const response = {
36247
36391
  classifications: rows.map((r) => ({
36248
36392
  domain: r.domain,
@@ -36262,7 +36406,7 @@ function lookupCachedBrief(db, projectId, targetRef, promptVersion) {
36262
36406
  if (promptVersion !== void 0) {
36263
36407
  conditions.push(eq49(recommendationBriefs.promptVersion, promptVersion));
36264
36408
  }
36265
- return db.select().from(recommendationBriefs).where(and43(...conditions)).orderBy(desc24(recommendationBriefs.generatedAt)).limit(1).get();
36409
+ return db.select().from(recommendationBriefs).where(and43(...conditions)).orderBy(desc25(recommendationBriefs.generatedAt)).limit(1).get();
36266
36410
  }
36267
36411
  function parseLimitParam(raw) {
36268
36412
  if (raw === void 0) return void 0;
@@ -38828,7 +38972,11 @@ var routeCatalog = [
38828
38972
  location: stringSchema,
38829
38973
  allLocations: booleanSchema,
38830
38974
  noLocation: booleanSchema,
38831
- dispatchMode: dispatchModeRequestSchema
38975
+ dispatchMode: dispatchModeRequestSchema,
38976
+ force: {
38977
+ type: "boolean",
38978
+ description: "Queue the run even when it would be refused with PROVIDERS_FAILING. Admission only; never stored."
38979
+ }
38832
38980
  }
38833
38981
  }
38834
38982
  }
@@ -38839,7 +38987,9 @@ var routeCatalog = [
38839
38987
  400: errorResponse(
38840
38988
  'Invalid request: an untracked query, a measurement scope naming a group/target/question the published plan does not contain, a scope combined with a query list, a per-run location on a plan project, a provider roster the plan was not published for, or `dispatchMode: "batch"` when no provider of the run can batch (`details.ineligible` names each provider\'s reason).'
38841
38989
  ),
38842
- 422: errorResponse("Project has no tracked queries."),
38990
+ 422: errorResponse(
38991
+ `NO_QUERIES: the project has no tracked queries. PROVIDERS_FAILING: every provider the run would call failed on its account (rejected key, denied access, no credit) in each of its last ${PROVIDER_ACCOUNT_FAILURE_STREAK} runs. \`details.providers\` names each provider's code and \`details.retryAfter\` when one run is let through again (${PROVIDER_ACCOUNT_RETRY_HOURS}h after the newest failure). Saving a new key, model or endpoint in a provider's settings lets the next run through at once, a probe is never refused, and \`force: true\` overrides.`
38992
+ ),
38843
38993
  409: errorResponse("Run already in progress."),
38844
38994
  503: errorResponse("No runnable answer provider is configured.")
38845
38995
  }
@@ -38893,7 +39043,11 @@ var routeCatalog = [
38893
39043
  properties: {
38894
39044
  kind: stringSchema,
38895
39045
  providers: stringArraySchema,
38896
- dispatchMode: dispatchModeRequestSchema
39046
+ dispatchMode: dispatchModeRequestSchema,
39047
+ force: {
39048
+ type: "boolean",
39049
+ description: "Queue projects that would be refused with PROVIDERS_FAILING. Admission only; never stored."
39050
+ }
38897
39051
  }
38898
39052
  }
38899
39053
  }
@@ -38902,7 +39056,7 @@ var routeCatalog = [
38902
39056
  responses: {
38903
39057
  // TODO: Add `TriggerAllRunsResponse` Zod schema in contracts.
38904
39058
  207: rawJsonResponse(
38905
- "One row per project: either a queued run or an error for that project alone. A project that cannot be measured (for example one whose published measurement plan expects a different number of answers per question) never prevents or hides the others.",
39059
+ "One row per project: either a queued run or an error for that project alone. A project that cannot be measured (for example one whose published measurement plan expects a different number of answers per question, or one whose providers all keep failing on their accounts: `errorCode: PROVIDERS_FAILING`) never prevents or hides the others.",
38906
39060
  { type: "array", items: looseObjectSchema }
38907
39061
  ),
38908
39062
  400: errorResponse("Invalid request: an unknown provider name, or an unsupported run kind.")
@@ -44150,7 +44304,7 @@ function buildOperationId(method, path8) {
44150
44304
 
44151
44305
  // ../api-routes/src/keys.ts
44152
44306
  import crypto25 from "crypto";
44153
- import { desc as desc25, eq as eq50 } from "drizzle-orm";
44307
+ import { desc as desc26, eq as eq50 } from "drizzle-orm";
44154
44308
  var KEYS_WRITE_SCOPE = "keys.write";
44155
44309
  function toApiKeyDto(row, projectNames) {
44156
44310
  const scopes = Array.isArray(row.scopes) ? row.scopes : [];
@@ -44175,7 +44329,7 @@ async function keysRoutes(app) {
44175
44329
  app.get("/keys", async (request) => {
44176
44330
  requireAdminSession(request);
44177
44331
  const scopedProjectId = request.apiKey?.projectId;
44178
- const rows = scopedProjectId ? app.db.select().from(apiKeys).where(eq50(apiKeys.projectId, scopedProjectId)).orderBy(desc25(apiKeys.createdAt)).all() : app.db.select().from(apiKeys).orderBy(desc25(apiKeys.createdAt)).all();
44332
+ const rows = scopedProjectId ? app.db.select().from(apiKeys).where(eq50(apiKeys.projectId, scopedProjectId)).orderBy(desc26(apiKeys.createdAt)).all() : app.db.select().from(apiKeys).orderBy(desc26(apiKeys.createdAt)).all();
44179
44333
  const names = projectNameById(app.db);
44180
44334
  return { keys: rows.map((row) => toApiKeyDto(row, names)) };
44181
44335
  });
@@ -45177,7 +45331,7 @@ function formatNotification(row) {
45177
45331
 
45178
45332
  // ../api-routes/src/google.ts
45179
45333
  import crypto33 from "crypto";
45180
- import { eq as eq54, and as and45, desc as desc26, sql as sql19, inArray as inArray24 } from "drizzle-orm";
45334
+ import { eq as eq54, and as and45, desc as desc27, sql as sql19, inArray as inArray25 } from "drizzle-orm";
45181
45335
 
45182
45336
  // ../api-routes/src/gsc-period-comparison.ts
45183
45337
  var DAY_MS = 864e5;
@@ -47688,9 +47842,9 @@ async function googleRoutes(app, opts) {
47688
47842
  const limitVal = Math.max(parseInt(limit ?? "500", 10) || 0, 1);
47689
47843
  const offsetVal = Math.max(parseInt(offset ?? "0", 10) || 0, 0);
47690
47844
  const orderColumns = {
47691
- clicks: [desc26(gscSearchData.clicks), desc26(gscSearchData.date), gscSearchData.query],
47692
- impressions: [desc26(gscSearchData.impressions), desc26(gscSearchData.date), gscSearchData.query],
47693
- date: [desc26(gscSearchData.date), desc26(gscSearchData.clicks), gscSearchData.query]
47845
+ clicks: [desc27(gscSearchData.clicks), desc27(gscSearchData.date), gscSearchData.query],
47846
+ impressions: [desc27(gscSearchData.impressions), desc27(gscSearchData.date), gscSearchData.query],
47847
+ date: [desc27(gscSearchData.date), desc27(gscSearchData.clicks), gscSearchData.query]
47694
47848
  }[orderBy];
47695
47849
  const rows = app.db.select().from(gscSearchData).where(and45(...conditions)).orderBy(...orderColumns).limit(limitVal).offset(offsetVal).all();
47696
47850
  const totalMatching = app.db.select({ total: sql19`COUNT(*)` }).from(gscSearchData).where(and45(...conditions)).get()?.total ?? 0;
@@ -47849,7 +48003,7 @@ async function googleRoutes(app, opts) {
47849
48003
  page: gscSearchData.page,
47850
48004
  clicks: sql19`COALESCE(SUM(${gscSearchData.clicks}), 0)`,
47851
48005
  impressions: sql19`COALESCE(SUM(${gscSearchData.impressions}), 0)`
47852
- }).from(gscSearchData).where(and45(...conditions)).groupBy(gscSearchData.page).orderBy(desc26(sql19`SUM(${gscSearchData.clicks})`), desc26(sql19`SUM(${gscSearchData.impressions})`)).limit(limitVal).all();
48006
+ }).from(gscSearchData).where(and45(...conditions)).groupBy(gscSearchData.page).orderBy(desc27(sql19`SUM(${gscSearchData.clicks})`), desc27(sql19`SUM(${gscSearchData.impressions})`)).limit(limitVal).all();
47853
48007
  const windowStart = startDate ?? cutoffDate ?? "";
47854
48008
  const windowEnd = endDate ?? resolvedWindow.endDate ?? "9999-12-31";
47855
48009
  const dailyTotals = readGscDailyTotals(app.db, project.id, windowStart, windowEnd);
@@ -47992,7 +48146,7 @@ async function googleRoutes(app, opts) {
47992
48146
  const { url, limit } = request.query;
47993
48147
  const conditions = [eq54(gscUrlInspections.projectId, project.id)];
47994
48148
  if (url) conditions.push(eq54(gscUrlInspections.url, url));
47995
- const rows = app.db.select().from(gscUrlInspections).where(and45(...conditions)).orderBy(desc26(gscUrlInspections.inspectedAt)).limit(parseInt(limit ?? "100", 10)).all();
48149
+ const rows = app.db.select().from(gscUrlInspections).where(and45(...conditions)).orderBy(desc27(gscUrlInspections.inspectedAt)).limit(parseInt(limit ?? "100", 10)).all();
47996
48150
  return rows.map((r) => ({
47997
48151
  id: r.id,
47998
48152
  url: r.url,
@@ -48011,7 +48165,7 @@ async function googleRoutes(app, opts) {
48011
48165
  });
48012
48166
  app.get("/projects/:name/google/gsc/deindexed", async (request) => {
48013
48167
  const project = resolveProject(app.db, request.params.name);
48014
- const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc26(gscUrlInspections.inspectedAt)).all();
48168
+ const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc27(gscUrlInspections.inspectedAt)).all();
48015
48169
  const byUrl = /* @__PURE__ */ new Map();
48016
48170
  for (const row of allInspections) {
48017
48171
  const existing = byUrl.get(row.url);
@@ -48039,7 +48193,7 @@ async function googleRoutes(app, opts) {
48039
48193
  });
48040
48194
  app.get("/projects/:name/google/gsc/coverage", async (request) => {
48041
48195
  const project = resolveProject(app.db, request.params.name);
48042
- const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc26(gscUrlInspections.inspectedAt)).all();
48196
+ const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc27(gscUrlInspections.inspectedAt)).all();
48043
48197
  const canonicalUrl = (url) => url.replace(/^http:\/\//, "https://");
48044
48198
  const latestByUrl = /* @__PURE__ */ new Map();
48045
48199
  const historyByUrl = /* @__PURE__ */ new Map();
@@ -48088,7 +48242,7 @@ async function googleRoutes(app, opts) {
48088
48242
  const total = latestByUrl.size;
48089
48243
  const indexed = indexedUrls.length;
48090
48244
  const notIndexed = notIndexedUrls.length;
48091
- const latestSnapshot = app.db.select({ createdAt: gscCoverageSnapshots.createdAt }).from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc26(gscCoverageSnapshots.createdAt)).limit(1).get();
48245
+ const latestSnapshot = app.db.select({ createdAt: gscCoverageSnapshots.createdAt }).from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc27(gscCoverageSnapshots.createdAt)).limit(1).get();
48092
48246
  const lastSyncedAt = latestSnapshot?.createdAt ?? null;
48093
48247
  const formatRow = (r) => ({
48094
48248
  id: r.id,
@@ -48144,7 +48298,7 @@ async function googleRoutes(app, opts) {
48144
48298
  const project = resolveProject(app.db, request.params.name);
48145
48299
  const parsed = parseInt(request.query.limit ?? "90", 10);
48146
48300
  const limit = Number.isNaN(parsed) || parsed <= 0 ? 90 : parsed;
48147
- const rows = app.db.select().from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc26(gscCoverageSnapshots.date)).limit(limit).all();
48301
+ const rows = app.db.select().from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc27(gscCoverageSnapshots.date)).limit(limit).all();
48148
48302
  return rows.map((r) => ({
48149
48303
  date: r.date,
48150
48304
  indexed: r.indexed,
@@ -48358,7 +48512,7 @@ async function googleRoutes(app, opts) {
48358
48512
  const { accessToken } = await getValidToken(store, project.canonicalDomain, "gsc", googleClientId, googleClientSecret);
48359
48513
  let urlsToNotify = request.body?.urls ?? [];
48360
48514
  if (request.body?.allUnindexed) {
48361
- const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc26(gscUrlInspections.inspectedAt)).all();
48515
+ const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc27(gscUrlInspections.inspectedAt)).all();
48362
48516
  const latestByUrl = /* @__PURE__ */ new Map();
48363
48517
  for (const row of allInspections) {
48364
48518
  if (!latestByUrl.has(row.url)) {
@@ -48725,7 +48879,7 @@ async function googleRoutes(app, opts) {
48725
48879
  const conditions = [eq54(gbpDailyMetrics.projectId, project.id)];
48726
48880
  if (request.query.locationName) conditions.push(eq54(gbpDailyMetrics.locationName, request.query.locationName));
48727
48881
  if (request.query.metric) conditions.push(eq54(gbpDailyMetrics.metric, request.query.metric));
48728
- const rows = app.db.select().from(gbpDailyMetrics).where(and45(...conditions)).orderBy(desc26(gbpDailyMetrics.date)).all();
48882
+ const rows = app.db.select().from(gbpDailyMetrics).where(and45(...conditions)).orderBy(desc27(gbpDailyMetrics.date)).all();
48729
48883
  return {
48730
48884
  metrics: rows.map((r) => ({ locationName: r.locationName, date: r.date, metric: r.metric, value: r.value })),
48731
48885
  total: rows.length
@@ -48772,7 +48926,7 @@ async function googleRoutes(app, opts) {
48772
48926
  const project = resolveProject(app.db, request.params.name);
48773
48927
  const conditions = [eq54(gbpLodgingSnapshots.projectId, project.id)];
48774
48928
  if (request.query.locationName) conditions.push(eq54(gbpLodgingSnapshots.locationName, request.query.locationName));
48775
- const rows = app.db.select().from(gbpLodgingSnapshots).where(and45(...conditions)).orderBy(desc26(gbpLodgingSnapshots.syncedAt)).all();
48929
+ const rows = app.db.select().from(gbpLodgingSnapshots).where(and45(...conditions)).orderBy(desc27(gbpLodgingSnapshots.syncedAt)).all();
48776
48930
  const latestByLocation = /* @__PURE__ */ new Map();
48777
48931
  for (const row of rows) {
48778
48932
  if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
@@ -48789,7 +48943,7 @@ async function googleRoutes(app, opts) {
48789
48943
  const project = resolveProject(app.db, request.params.name);
48790
48944
  const conditions = [eq54(gbpAttributesSnapshots.projectId, project.id)];
48791
48945
  if (request.query.locationName) conditions.push(eq54(gbpAttributesSnapshots.locationName, request.query.locationName));
48792
- const rows = app.db.select().from(gbpAttributesSnapshots).where(and45(...conditions)).orderBy(desc26(gbpAttributesSnapshots.syncedAt)).all();
48946
+ const rows = app.db.select().from(gbpAttributesSnapshots).where(and45(...conditions)).orderBy(desc27(gbpAttributesSnapshots.syncedAt)).all();
48793
48947
  const latestByLocation = /* @__PURE__ */ new Map();
48794
48948
  for (const row of rows) {
48795
48949
  if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
@@ -48809,7 +48963,7 @@ async function googleRoutes(app, opts) {
48809
48963
  const project = resolveProject(app.db, request.params.name);
48810
48964
  const conditions = [eq54(gbpPlaceDetails.projectId, project.id)];
48811
48965
  if (request.query.locationName) conditions.push(eq54(gbpPlaceDetails.locationName, request.query.locationName));
48812
- const rows = app.db.select().from(gbpPlaceDetails).where(and45(...conditions)).orderBy(desc26(gbpPlaceDetails.syncedAt)).all();
48966
+ const rows = app.db.select().from(gbpPlaceDetails).where(and45(...conditions)).orderBy(desc27(gbpPlaceDetails.syncedAt)).all();
48813
48967
  const latestByLocation = /* @__PURE__ */ new Map();
48814
48968
  for (const row of rows) {
48815
48969
  if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
@@ -48836,7 +48990,7 @@ async function googleRoutes(app, opts) {
48836
48990
  locationName ? eq54(gbpLocations.locationName, locationName) : eq54(gbpLocations.selected, true)
48837
48991
  )).orderBy(gbpLocations.displayName).all();
48838
48992
  const latestRating = /* @__PURE__ */ new Map();
48839
- for (const row of app.db.select().from(gbpReviewRatings).where(eq54(gbpReviewRatings.projectId, project.id)).orderBy(desc26(gbpReviewRatings.observedAt)).all()) {
48993
+ for (const row of app.db.select().from(gbpReviewRatings).where(eq54(gbpReviewRatings.projectId, project.id)).orderBy(desc27(gbpReviewRatings.observedAt)).all()) {
48840
48994
  if (!latestRating.has(row.locationName)) latestRating.set(row.locationName, row);
48841
48995
  }
48842
48996
  const locations = locationRows.map((loc) => {
@@ -48857,7 +49011,7 @@ async function googleRoutes(app, opts) {
48857
49011
  if (locationName) conditions.push(eq54(gbpReviews.locationName, locationName));
48858
49012
  if (negativeOnly) conditions.push(sql19`${gbpReviews.starRating} BETWEEN 1 AND ${negativeMaxStars}`);
48859
49013
  const total = app.db.select({ n: sql19`count(*)` }).from(gbpReviews).where(and45(...conditions)).get()?.n ?? 0;
48860
- const reviews = app.db.select().from(gbpReviews).where(and45(...conditions)).orderBy(desc26(gbpReviews.updateTime), gbpReviews.reviewName).limit(limit).all().map((r) => ({
49014
+ const reviews = app.db.select().from(gbpReviews).where(and45(...conditions)).orderBy(desc27(gbpReviews.updateTime), gbpReviews.reviewName).limit(limit).all().map((r) => ({
48861
49015
  locationName: r.locationName,
48862
49016
  origin: r.origin,
48863
49017
  reviewName: r.reviewName,
@@ -48896,10 +49050,10 @@ async function googleRoutes(app, opts) {
48896
49050
  locationProfiles: []
48897
49051
  });
48898
49052
  }
48899
- const metricRows = app.db.select().from(gbpDailyMetrics).where(and45(eq54(gbpDailyMetrics.projectId, project.id), inArray24(gbpDailyMetrics.locationName, locationNames))).all();
48900
- const keywordRows = app.db.select().from(gbpKeywordImpressions).where(and45(eq54(gbpKeywordImpressions.projectId, project.id), inArray24(gbpKeywordImpressions.locationName, locationNames))).all();
48901
- const placeActionRows = app.db.select().from(gbpPlaceActions).where(and45(eq54(gbpPlaceActions.projectId, project.id), inArray24(gbpPlaceActions.locationName, locationNames))).all();
48902
- const lodgingRows = app.db.select().from(gbpLodgingSnapshots).where(and45(eq54(gbpLodgingSnapshots.projectId, project.id), inArray24(gbpLodgingSnapshots.locationName, locationNames))).orderBy(desc26(gbpLodgingSnapshots.syncedAt)).all();
49053
+ const metricRows = app.db.select().from(gbpDailyMetrics).where(and45(eq54(gbpDailyMetrics.projectId, project.id), inArray25(gbpDailyMetrics.locationName, locationNames))).all();
49054
+ const keywordRows = app.db.select().from(gbpKeywordImpressions).where(and45(eq54(gbpKeywordImpressions.projectId, project.id), inArray25(gbpKeywordImpressions.locationName, locationNames))).all();
49055
+ const placeActionRows = app.db.select().from(gbpPlaceActions).where(and45(eq54(gbpPlaceActions.projectId, project.id), inArray25(gbpPlaceActions.locationName, locationNames))).all();
49056
+ const lodgingRows = app.db.select().from(gbpLodgingSnapshots).where(and45(eq54(gbpLodgingSnapshots.projectId, project.id), inArray25(gbpLodgingSnapshots.locationName, locationNames))).orderBy(desc27(gbpLodgingSnapshots.syncedAt)).all();
48903
49057
  const latestLodgingByLocation = /* @__PURE__ */ new Map();
48904
49058
  for (const row of lodgingRows) {
48905
49059
  if (!latestLodgingByLocation.has(row.locationName)) {
@@ -48913,7 +49067,7 @@ async function googleRoutes(app, opts) {
48913
49067
  regularHours: gbpLocations.regularHours,
48914
49068
  primaryPhone: gbpLocations.primaryPhone,
48915
49069
  openStatus: gbpLocations.openStatus
48916
- }).from(gbpLocations).where(and45(eq54(gbpLocations.projectId, project.id), inArray24(gbpLocations.locationName, locationNames))).all();
49070
+ }).from(gbpLocations).where(and45(eq54(gbpLocations.projectId, project.id), inArray25(gbpLocations.locationName, locationNames))).all();
48917
49071
  return buildGbpSummary({
48918
49072
  locationName,
48919
49073
  locationCount: locationNames.length,
@@ -48944,7 +49098,7 @@ function parseReviewLimit(value) {
48944
49098
 
48945
49099
  // ../api-routes/src/google-marketing.ts
48946
49100
  import crypto34 from "crypto";
48947
- import { and as and46, desc as desc27, eq as eq55, isNull as isNull10, lt as lt9, ne as ne10, or as or13, sql as sql20 } from "drizzle-orm";
49101
+ import { and as and46, desc as desc28, eq as eq55, isNull as isNull10, lt as lt9, ne as ne10, or as or13, sql as sql20 } from "drizzle-orm";
48948
49102
  import { z as z4 } from "zod";
48949
49103
  var snapshotPageQuerySchema = z4.object({
48950
49104
  limit: z4.coerce.number().int().min(1).max(GOOGLE_MARKETING_STORED_SNAPSHOT_PAGE_MAX).optional(),
@@ -50160,7 +50314,7 @@ async function googleMarketingRoutes(app, opts) {
50160
50314
  eq55(runs.projectId, project.id),
50161
50315
  eq55(runs.kind, RunKinds["google-ads-sync"]),
50162
50316
  or13(eq55(runs.status, RunStatuses.queued), eq55(runs.status, RunStatuses.running))
50163
- )).orderBy(desc27(runs.createdAt)).get();
50317
+ )).orderBy(desc28(runs.createdAt)).get();
50164
50318
  if (existing) {
50165
50319
  run = existing;
50166
50320
  return;
@@ -50196,7 +50350,7 @@ async function googleMarketingRoutes(app, opts) {
50196
50350
  eq55(runs.projectId, project.id),
50197
50351
  eq55(runs.kind, RunKinds["gtm-sync"]),
50198
50352
  or13(eq55(runs.status, RunStatuses.queued), eq55(runs.status, RunStatuses.running))
50199
- )).orderBy(desc27(runs.createdAt)).get();
50353
+ )).orderBy(desc28(runs.createdAt)).get();
50200
50354
  if (existing) {
50201
50355
  run = existing;
50202
50356
  return;
@@ -50231,7 +50385,7 @@ async function googleMarketingRoutes(app, opts) {
50231
50385
  ));
50232
50386
  }
50233
50387
  const limit = query.limit ?? 50;
50234
- const rows = app.db.select().from(googleAdsRawSnapshots).where(and46(...conditions)).orderBy(desc27(googleAdsRawSnapshots.capturedAt), desc27(googleAdsRawSnapshots.id)).limit(limit + 1).all();
50388
+ const rows = app.db.select().from(googleAdsRawSnapshots).where(and46(...conditions)).orderBy(desc28(googleAdsRawSnapshots.capturedAt), desc28(googleAdsRawSnapshots.id)).limit(limit + 1).all();
50235
50389
  const page3 = rows.slice(0, limit);
50236
50390
  const total = app.db.select({ total: sql20`COUNT(*)`.mapWith(Number).as("total") }).from(googleAdsRawSnapshots).where(eq55(googleAdsRawSnapshots.projectId, project.id)).get();
50237
50391
  return {
@@ -50263,7 +50417,7 @@ async function googleMarketingRoutes(app, opts) {
50263
50417
  ));
50264
50418
  }
50265
50419
  const limit = query.limit ?? 50;
50266
- const rows = app.db.select().from(gtmRawSnapshots).where(and46(...conditions)).orderBy(desc27(gtmRawSnapshots.capturedAt), desc27(gtmRawSnapshots.id)).limit(limit + 1).all();
50420
+ const rows = app.db.select().from(gtmRawSnapshots).where(and46(...conditions)).orderBy(desc28(gtmRawSnapshots.capturedAt), desc28(gtmRawSnapshots.id)).limit(limit + 1).all();
50267
50421
  const page3 = rows.slice(0, limit);
50268
50422
  const total = app.db.select({ total: sql20`COUNT(*)`.mapWith(Number).as("total") }).from(gtmRawSnapshots).where(eq55(gtmRawSnapshots.projectId, project.id)).get();
50269
50423
  return {
@@ -50534,7 +50688,7 @@ async function googleMarketingRoutes(app, opts) {
50534
50688
 
50535
50689
  // ../api-routes/src/ads.ts
50536
50690
  import crypto37 from "crypto";
50537
- import { eq as eq57, and as and48, asc as asc11, desc as desc28, gt as gt5, gte as gte14, lt as lt10, lte as lte14, ne as ne11, inArray as inArray25, or as or15, isNull as isNull12, isNotNull as isNotNull7, sql as sql22 } from "drizzle-orm";
50691
+ import { eq as eq57, and as and48, asc as asc11, desc as desc29, gt as gt6, gte as gte14, lt as lt10, lte as lte14, ne as ne11, inArray as inArray26, or as or15, isNull as isNull12, isNotNull as isNotNull7, sql as sql22 } from "drizzle-orm";
50538
50692
 
50539
50693
  // ../api-routes/src/ads-activation.ts
50540
50694
  import crypto35 from "crypto";
@@ -51920,7 +52074,7 @@ async function executeApprovedAdsActivation(dependencies, request) {
51920
52074
 
51921
52075
  // ../api-routes/src/ads-activation-routes.ts
51922
52076
  import crypto36 from "crypto";
51923
- import { and as and47, asc as asc10, eq as eq56, gt as gt4, isNotNull as isNotNull6, isNull as isNull11, lte as lte13, or as or14, sql as sql21 } from "drizzle-orm";
52077
+ import { and as and47, asc as asc10, eq as eq56, gt as gt5, isNotNull as isNotNull6, isNull as isNull11, lte as lte13, or as or14, sql as sql21 } from "drizzle-orm";
51924
52078
  var MAX_ACTIVATION_GRANT_LIFETIME_MS = 24 * 60 * 60 * 1e3;
51925
52079
  var ACTIVATION_LEASE_MS = 5 * 6e4;
51926
52080
  var ACTIVATION_REVOCATION_SETTLEMENT_MS = ACTIVATION_LEASE_MS;
@@ -52141,7 +52295,7 @@ function createActivationStore(app, request) {
52141
52295
  eq56(adsOperations.id, input.operationId),
52142
52296
  eq56(adsOperations.state, AdsOperationStates.pending),
52143
52297
  eq56(adsOperations.leaseOwner, input.leaseOwner),
52144
- gt4(adsOperations.leaseExpiresAt, input.now)
52298
+ gt5(adsOperations.leaseExpiresAt, input.now)
52145
52299
  )).run();
52146
52300
  const operation = loadActivationOperation(tx, input.operationId);
52147
52301
  if (!operation) throw internalError("Ads activation receipt was not found");
@@ -52197,7 +52351,7 @@ function createActivationStore(app, request) {
52197
52351
  eq56(adsOperations.id, input.operationId),
52198
52352
  eq56(adsOperations.state, AdsOperationStates.pending),
52199
52353
  eq56(adsOperations.leaseOwner, input.leaseOwner),
52200
- gt4(adsOperations.leaseExpiresAt, input.next.updatedAt)
52354
+ gt5(adsOperations.leaseExpiresAt, input.next.updatedAt)
52201
52355
  )).run();
52202
52356
  if (lease.changes !== 1 || existing.state !== input.fromState) {
52203
52357
  const current2 = loadActivationOperation(tx, input.operationId);
@@ -52239,7 +52393,7 @@ function createActivationStore(app, request) {
52239
52393
  eq56(adsOperations.id, input.operationId),
52240
52394
  eq56(adsOperations.state, AdsOperationStates.pending),
52241
52395
  eq56(adsOperations.leaseOwner, input.leaseOwner),
52242
- gt4(adsOperations.leaseExpiresAt, input.next.updatedAt)
52396
+ gt5(adsOperations.leaseExpiresAt, input.next.updatedAt)
52243
52397
  )).run();
52244
52398
  if (lease.changes !== 1 || existing.state !== input.fromState) {
52245
52399
  const operation2 = loadActivationOperation(tx, input.operationId);
@@ -52302,7 +52456,7 @@ function createActivationStore(app, request) {
52302
52456
  eq56(adsOperations.id, input.operationId),
52303
52457
  eq56(adsOperations.state, AdsOperationStates.pending),
52304
52458
  eq56(adsOperations.leaseOwner, input.leaseOwner),
52305
- gt4(adsOperations.leaseExpiresAt, input.now)
52459
+ gt5(adsOperations.leaseExpiresAt, input.now)
52306
52460
  )).run();
52307
52461
  if (operationUpdate.changes === 1) {
52308
52462
  const grantUpdate = tx.update(adsActivationGrants).set({
@@ -53578,7 +53732,7 @@ function semanticallyMatchesMaterializedEntity(app, input) {
53578
53732
  eq57(adsOperations.projectId, input.projectId),
53579
53733
  eq57(adsOperations.entityType, input.entityType),
53580
53734
  eq57(adsOperations.entityId, input.entityId),
53581
- inArray25(adsOperations.kind, [createKind, updateKind])
53735
+ inArray26(adsOperations.kind, [createKind, updateKind])
53582
53736
  )).orderBy(asc11(adsOperations.createdAt), asc11(adsOperations.id)).all();
53583
53737
  if (rows.some((row) => row.state === AdsOperationStates.pending || row.state === AdsOperationStates.reconciling || row.state === AdsOperationStates.unknown || row.kind === updateKind && row.state === AdsOperationStates.succeeded)) {
53584
53738
  return false;
@@ -54015,7 +54169,7 @@ function quarantineExhaustedReconciliation(app, row, now, policy, context) {
54015
54169
  eq57(adsOperations.id, row.id),
54016
54170
  eq57(adsOperations.projectId, row.projectId),
54017
54171
  gte14(adsOperations.reconcileAttempts, policy.maxAttempts),
54018
- inArray25(adsOperations.state, [
54172
+ inArray26(adsOperations.state, [
54019
54173
  AdsOperationStates.pending,
54020
54174
  AdsOperationStates.unknown,
54021
54175
  AdsOperationStates.reconciling
@@ -54239,7 +54393,7 @@ async function sweepAdsOperationsOnce(app, opts, config) {
54239
54393
  eq57(adsOperations.reconcileStrategy, AdsReconcileStrategies.create_fingerprint),
54240
54394
  or15(
54241
54395
  isNotNull7(adsOperations.entityId),
54242
- inArray25(adsOperations.state, [
54396
+ inArray26(adsOperations.state, [
54243
54397
  AdsOperationStates.pending,
54244
54398
  AdsOperationStates.reconciling
54245
54399
  ])
@@ -54287,7 +54441,7 @@ async function sweepAdsOperationsOnce(app, opts, config) {
54287
54441
  const eligibleProjectIds = [...credentialsByProjectId.keys()];
54288
54442
  if (eligibleProjectIds.length === 0) return;
54289
54443
  const rows = app.db.select().from(adsOperations).where(and48(
54290
- inArray25(adsOperations.projectId, eligibleProjectIds),
54444
+ inArray26(adsOperations.projectId, eligibleProjectIds),
54291
54445
  staleReconcileWhere
54292
54446
  )).orderBy(asc11(adsOperations.updatedAt)).limit(config.batchSize).all();
54293
54447
  for (const row of rows) {
@@ -54609,12 +54763,12 @@ async function adsRoutes(app, opts) {
54609
54763
  const cursor = parsed.data.cursor ? decodeAdsOperationCursor(parsed.data.cursor, project.id, parsed.data.state) : void 0;
54610
54764
  const rows = app.db.select().from(adsOperations).where(and48(
54611
54765
  eq57(adsOperations.projectId, project.id),
54612
- inArray25(adsOperations.state, parsed.data.state),
54766
+ inArray26(adsOperations.state, parsed.data.state),
54613
54767
  cursor ? or15(
54614
- gt5(adsOperations.createdAt, cursor.createdAt),
54768
+ gt6(adsOperations.createdAt, cursor.createdAt),
54615
54769
  and48(
54616
54770
  eq57(adsOperations.createdAt, cursor.createdAt),
54617
- gt5(adsOperations.id, cursor.id)
54771
+ gt6(adsOperations.id, cursor.id)
54618
54772
  )
54619
54773
  ) : void 0
54620
54774
  )).orderBy(asc11(adsOperations.createdAt), asc11(adsOperations.id)).limit(parsed.data.limit + 1).all();
@@ -55043,7 +55197,7 @@ async function adsRoutes(app, opts) {
55043
55197
  const inFlight = app.db.select({ id: runs.id, status: runs.status }).from(runs).where(and48(
55044
55198
  eq57(runs.projectId, project.id),
55045
55199
  eq57(runs.kind, RunKinds["ads-sync"]),
55046
- inArray25(runs.status, [RunStatuses.queued, RunStatuses.running])
55200
+ inArray26(runs.status, [RunStatuses.queued, RunStatuses.running])
55047
55201
  )).get();
55048
55202
  if (inFlight) {
55049
55203
  const existing = { runId: inFlight.id, status: inFlight.status };
@@ -55174,7 +55328,7 @@ async function adsRoutes(app, opts) {
55174
55328
  const latestAdsSync = app.db.select({ id: runs.id, kind: runs.kind, status: runs.status }).from(runs).where(and48(
55175
55329
  eq57(runs.projectId, project.id),
55176
55330
  eq57(runs.kind, RunKinds["ads-sync"])
55177
- )).orderBy(desc28(runs.createdAt)).get();
55331
+ )).orderBy(desc29(runs.createdAt)).get();
55178
55332
  const snapshot = storedSnapshotProvenance({
55179
55333
  connected: Boolean(connection),
55180
55334
  connectionLastSyncedAt: connection?.lastSyncedAt ?? null,
@@ -55578,7 +55732,7 @@ async function adsRoutes(app, opts) {
55578
55732
 
55579
55733
  // ../api-routes/src/bing.ts
55580
55734
  import crypto39 from "crypto";
55581
- import { eq as eq58, and as and49, desc as desc29 } from "drizzle-orm";
55735
+ import { eq as eq58, and as and49, desc as desc30 } from "drizzle-orm";
55582
55736
 
55583
55737
  // ../integration-bing/src/bing-client.ts
55584
55738
  import crypto38 from "crypto";
@@ -55997,7 +56151,7 @@ async function bingRoutes(app, opts) {
55997
56151
  const store = requireConnectionStore();
55998
56152
  const project = resolveProject(app.db, request.params.name);
55999
56153
  requireConnection(store, project.canonicalDomain);
56000
- const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc29(bingUrlInspections.inspectedAt)).all();
56154
+ const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc30(bingUrlInspections.inspectedAt)).all();
56001
56155
  const latestByUrl = /* @__PURE__ */ new Map();
56002
56156
  const definitiveByUrl = /* @__PURE__ */ new Map();
56003
56157
  for (const row of allInspections) {
@@ -56086,7 +56240,7 @@ async function bingRoutes(app, opts) {
56086
56240
  const project = resolveProject(app.db, request.params.name);
56087
56241
  const parsed = parseInt(request.query.limit ?? "90", 10);
56088
56242
  const limit = Number.isNaN(parsed) || parsed <= 0 ? 90 : parsed;
56089
- const rows = app.db.select().from(bingCoverageSnapshots).where(eq58(bingCoverageSnapshots.projectId, project.id)).orderBy(desc29(bingCoverageSnapshots.date)).limit(limit).all();
56243
+ const rows = app.db.select().from(bingCoverageSnapshots).where(eq58(bingCoverageSnapshots.projectId, project.id)).orderBy(desc30(bingCoverageSnapshots.date)).limit(limit).all();
56090
56244
  return rows.map((r) => ({
56091
56245
  date: r.date,
56092
56246
  indexed: r.indexed,
@@ -56099,7 +56253,7 @@ async function bingRoutes(app, opts) {
56099
56253
  const project = resolveProject(app.db, request.params.name);
56100
56254
  const { url, limit } = request.query;
56101
56255
  const whereClause = url ? and49(eq58(bingUrlInspections.projectId, project.id), eq58(bingUrlInspections.url, url)) : eq58(bingUrlInspections.projectId, project.id);
56102
- const filtered = app.db.select().from(bingUrlInspections).where(whereClause).orderBy(desc29(bingUrlInspections.inspectedAt)).limit(Math.max(1, Math.min(parseInt(limit ?? "100", 10) || 100, 1e3))).all();
56256
+ const filtered = app.db.select().from(bingUrlInspections).where(whereClause).orderBy(desc30(bingUrlInspections.inspectedAt)).limit(Math.max(1, Math.min(parseInt(limit ?? "100", 10) || 100, 1e3))).all();
56103
56257
  return filtered.map((r) => ({
56104
56258
  id: r.id,
56105
56259
  url: r.url,
@@ -56243,7 +56397,7 @@ async function bingRoutes(app, opts) {
56243
56397
  }
56244
56398
  let urlsToSubmit = request.body?.urls ?? [];
56245
56399
  if (request.body?.allUnindexed) {
56246
- const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc29(bingUrlInspections.inspectedAt)).all();
56400
+ const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc30(bingUrlInspections.inspectedAt)).all();
56247
56401
  const latestByUrl = /* @__PURE__ */ new Map();
56248
56402
  for (const row of allInspections) {
56249
56403
  if (!latestByUrl.has(row.url)) {
@@ -56502,7 +56656,7 @@ async function cdpRoutes(app, opts) {
56502
56656
 
56503
56657
  // ../api-routes/src/ga.ts
56504
56658
  import crypto40 from "crypto";
56505
- import { eq as eq60, desc as desc30, and as and51, sql as sql23 } from "drizzle-orm";
56659
+ import { eq as eq60, desc as desc31, and as and51, sql as sql23 } from "drizzle-orm";
56506
56660
 
56507
56661
  // ../api-routes/src/ga-session-history.ts
56508
56662
  function buildSessionHistory(landingPageDays, dailyTotals) {
@@ -56978,7 +57132,7 @@ async function ga4Routes(app, opts) {
56978
57132
  if (!connected) {
56979
57133
  return { connected: false, propertyId: null, clientEmail: null, authMethod: null, lastSyncedAt: null };
56980
57134
  }
56981
- const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc30(gaTrafficSummaries.syncedAt)).limit(1).get();
57135
+ const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc31(gaTrafficSummaries.syncedAt)).limit(1).get();
56982
57136
  return {
56983
57137
  connected: true,
56984
57138
  propertyId: saConn?.propertyId ?? oauthConn?.propertyId ?? null,
@@ -57408,7 +57562,7 @@ async function ga4Routes(app, opts) {
57408
57562
  const socialTotals = app.db.select({
57409
57563
  sessions: sql23`SUM(${gaSocialReferrals.sessions})`
57410
57564
  }).from(gaSocialReferrals).where(and51(...socialConditions)).get();
57411
- const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc30(gaTrafficSummaries.syncedAt)).limit(1).get();
57565
+ const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc31(gaTrafficSummaries.syncedAt)).limit(1).get();
57412
57566
  const total = summaryRow?.totalSessions ?? 0;
57413
57567
  const totalDirectSessions = directTotalRow?.totalDirectSessions ?? 0;
57414
57568
  const totalOrganicSessions = summaryRow?.totalOrganicSessions ?? 0;
@@ -59360,7 +59514,7 @@ async function wordpressRoutes(app, opts) {
59360
59514
 
59361
59515
  // ../api-routes/src/backlinks.ts
59362
59516
  import crypto42 from "crypto";
59363
- import { and as and53, asc as asc12, desc as desc31, eq as eq61, sql as sql24 } from "drizzle-orm";
59517
+ import { and as and53, asc as asc12, desc as desc32, eq as eq61, sql as sql24 } from "drizzle-orm";
59364
59518
 
59365
59519
  // ../integration-commoncrawl/src/constants.ts
59366
59520
  import os2 from "os";
@@ -59861,7 +60015,7 @@ function latestSummaryForProject(db, projectId, source, release) {
59861
60015
  eq61(backlinkSummaries.source, source)
59862
60016
  ];
59863
60017
  if (release) conditions.push(eq61(backlinkSummaries.release, release));
59864
- return db.select().from(backlinkSummaries).where(and53(...conditions)).orderBy(desc31(backlinkSummaries.queriedAt)).limit(1).get();
60018
+ return db.select().from(backlinkSummaries).where(and53(...conditions)).orderBy(desc32(backlinkSummaries.queriedAt)).limit(1).get();
59865
60019
  }
59866
60020
  function parseExcludeCrawlers(value) {
59867
60021
  if (!value) return false;
@@ -59883,7 +60037,7 @@ function computeFilteredSummary(db, base) {
59883
60037
  count: sql24`count(*)`,
59884
60038
  total: sql24`coalesce(sum(${backlinkDomains.numHosts}), 0)`
59885
60039
  }).from(backlinkDomains).where(filteredCondition).get();
59886
- const top10Rows = db.select({ numHosts: backlinkDomains.numHosts }).from(backlinkDomains).where(filteredCondition).orderBy(desc31(backlinkDomains.numHosts)).limit(10).all();
60040
+ const top10Rows = db.select({ numHosts: backlinkDomains.numHosts }).from(backlinkDomains).where(filteredCondition).orderBy(desc32(backlinkDomains.numHosts)).limit(10).all();
59887
60041
  const totalLinkingDomains = Number(filteredAgg?.count ?? 0);
59888
60042
  const totalHosts = Number(filteredAgg?.total ?? 0);
59889
60043
  const unfilteredLinkingDomains = Number(unfilteredAgg?.count ?? 0);
@@ -59904,7 +60058,7 @@ function computeFilteredSummary(db, base) {
59904
60058
  };
59905
60059
  }
59906
60060
  function buildSourceAvailability(db, projectId, source, connected, excludeCrawlers) {
59907
- const summary3 = db.select().from(backlinkSummaries).where(and53(eq61(backlinkSummaries.projectId, projectId), eq61(backlinkSummaries.source, source))).orderBy(desc31(backlinkSummaries.queriedAt)).limit(1).get();
60061
+ const summary3 = db.select().from(backlinkSummaries).where(and53(eq61(backlinkSummaries.projectId, projectId), eq61(backlinkSummaries.source, source))).orderBy(desc32(backlinkSummaries.queriedAt)).limit(1).get();
59908
60062
  let totalLinkingDomains = summary3?.totalLinkingDomains ?? 0;
59909
60063
  if (summary3 && excludeCrawlers) {
59910
60064
  const filtered = db.select({ count: sql24`count(*)` }).from(backlinkDomains).where(and53(
@@ -60009,11 +60163,11 @@ async function backlinksRoutes(app, opts) {
60009
60163
  return reply.status(201).send(mapSyncRow(inserted));
60010
60164
  });
60011
60165
  app.get("/backlinks/syncs/latest", async (_request, reply) => {
60012
- const row = app.db.select().from(ccReleaseSyncs).orderBy(desc31(ccReleaseSyncs.updatedAt)).limit(1).get();
60166
+ const row = app.db.select().from(ccReleaseSyncs).orderBy(desc32(ccReleaseSyncs.updatedAt)).limit(1).get();
60013
60167
  return reply.send(row ? mapSyncRow(row) : null);
60014
60168
  });
60015
60169
  app.get("/backlinks/syncs", async (_request, reply) => {
60016
- const rows = app.db.select().from(ccReleaseSyncs).orderBy(desc31(ccReleaseSyncs.updatedAt)).all();
60170
+ const rows = app.db.select().from(ccReleaseSyncs).orderBy(desc32(ccReleaseSyncs.updatedAt)).all();
60017
60171
  return reply.send(rows.map(mapSyncRow));
60018
60172
  });
60019
60173
  app.get("/backlinks/releases", async (_request, reply) => {
@@ -60100,7 +60254,7 @@ async function backlinksRoutes(app, opts) {
60100
60254
  linkingDomain: backlinkDomains.linkingDomain,
60101
60255
  numHosts: backlinkDomains.numHosts,
60102
60256
  source: backlinkDomains.source
60103
- }).from(backlinkDomains).where(domainCondition).orderBy(desc31(backlinkDomains.numHosts)).limit(limit).offset(offset).all();
60257
+ }).from(backlinkDomains).where(domainCondition).orderBy(desc32(backlinkDomains.numHosts)).limit(limit).offset(offset).all();
60104
60258
  let summary3 = null;
60105
60259
  if (summaryRow) {
60106
60260
  summary3 = excludeCrawlers ? computeFilteredSummary(app.db, summaryRow) : mapSummaryRow(summaryRow);
@@ -60146,7 +60300,7 @@ import crypto45 from "crypto";
60146
60300
  import { isIP } from "net";
60147
60301
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
60148
60302
  import { Agent as UndiciAgent } from "undici";
60149
- import { and as and57, desc as desc32, eq as eq65, gte as gte16, inArray as inArray26, lte as lte17, sql as sql27 } from "drizzle-orm";
60303
+ import { and as and57, desc as desc33, eq as eq65, gte as gte16, inArray as inArray27, lte as lte17, sql as sql27 } from "drizzle-orm";
60150
60304
 
60151
60305
  // ../api-routes/src/cloudflare-worker-version.ts
60152
60306
  var CURRENT_CLOUDFLARE_WORKER_VERSION = "1.0.1";
@@ -79330,7 +79484,8 @@ async function trafficRoutes(app, opts) {
79330
79484
  allEvents = drained.events;
79331
79485
  } catch (e) {
79332
79486
  const msg = describeError(e);
79333
- markFailed(msg, "PROVIDER_PULL");
79487
+ const credentialRefused = e instanceof VercelLogsApiError && (e.status === 401 || e.status === 403);
79488
+ markFailed(msg, credentialRefused ? "PROVIDER_AUTH" : "PROVIDER_PULL");
79334
79489
  throw providerError(`Vercel pull failed: ${msg}`);
79335
79490
  }
79336
79491
  }
@@ -79887,7 +80042,7 @@ async function trafficRoutes(app, opts) {
79887
80042
  eq65(runs.kind, RunKinds["traffic-sync"]),
79888
80043
  eq65(runs.sourceId, row.id)
79889
80044
  )
79890
- ).orderBy(desc32(runs.startedAt)).limit(1).get();
80045
+ ).orderBy(desc33(runs.startedAt)).limit(1).get();
79891
80046
  return {
79892
80047
  ...rowToDto(row),
79893
80048
  totals24h: {
@@ -79966,14 +80121,14 @@ async function trafficRoutes(app, opts) {
79966
80121
  });
79967
80122
  app.get("/projects/:name/traffic/sources", async (request) => {
79968
80123
  const project = resolveProject(app.db, request.params.name);
79969
- const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc32(trafficSources.createdAt)).all();
80124
+ const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc33(trafficSources.createdAt)).all();
79970
80125
  const sources = rows.filter((row) => row.status !== TrafficSourceStatuses.archived).map(rowToDto);
79971
80126
  const response = { sources };
79972
80127
  return response;
79973
80128
  });
79974
80129
  app.get("/projects/:name/traffic/status", async (request) => {
79975
80130
  const project = resolveProject(app.db, request.params.name);
79976
- const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc32(trafficSources.createdAt)).all();
80131
+ const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc33(trafficSources.createdAt)).all();
79977
80132
  const since = new Date(Date.now() - 24 * 60 * 6e4).toISOString();
79978
80133
  const sources = rows.filter((row) => row.status !== TrafficSourceStatuses.archived).map((row) => buildSourceDetail(project.id, row, since));
79979
80134
  const response = { sources };
@@ -80084,7 +80239,7 @@ async function trafficRoutes(app, opts) {
80084
80239
  const listed = useContentList ? contentPaths : infraPaths;
80085
80240
  const IN_LIST_CAP = 2e4;
80086
80241
  const listFitsInSql = listed.length <= IN_LIST_CAP;
80087
- const contentExpr = listed.length === 0 ? useContentList ? sql27`0` : sql27`${crawlerEventsHourly.hits}` : useContentList ? sql27`CASE WHEN ${inArray26(crawlerEventsHourly.pathNormalized, listed)} THEN ${crawlerEventsHourly.hits} ELSE 0 END` : sql27`CASE WHEN ${inArray26(crawlerEventsHourly.pathNormalized, listed)} THEN 0 ELSE ${crawlerEventsHourly.hits} END`;
80242
+ const contentExpr = listed.length === 0 ? useContentList ? sql27`0` : sql27`${crawlerEventsHourly.hits}` : useContentList ? sql27`CASE WHEN ${inArray27(crawlerEventsHourly.pathNormalized, listed)} THEN ${crawlerEventsHourly.hits} ELSE 0 END` : sql27`CASE WHEN ${inArray27(crawlerEventsHourly.pathNormalized, listed)} THEN 0 ELSE ${crawlerEventsHourly.hits} END`;
80088
80243
  if (listFitsInSql) {
80089
80244
  const crawlerSeries = app.db.select({
80090
80245
  bucket: crawlerSeriesBucket,
@@ -80111,7 +80266,7 @@ async function trafficRoutes(app, opts) {
80111
80266
  if (useContentList ? inList : !inList) point.crawlerContentHits += hits;
80112
80267
  }
80113
80268
  }
80114
- const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(desc32(crawlerEventsHourly.tsHour)).limit(limit).all();
80269
+ const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(desc33(crawlerEventsHourly.tsHour)).limit(limit).all();
80115
80270
  for (const r of rows) {
80116
80271
  events.push({
80117
80272
  kind: TrafficEventKinds.crawler,
@@ -80151,7 +80306,7 @@ async function trafficRoutes(app, opts) {
80151
80306
  for (const row of userFetchSeries) {
80152
80307
  trafficSeriesPoint(seriesByBucket, row.bucket).aiUserFetchHits = Number(row.hits);
80153
80308
  }
80154
- const rows = app.db.select().from(aiUserFetchEventsHourly).where(userFetchWhere).orderBy(desc32(aiUserFetchEventsHourly.tsHour)).limit(limit).all();
80309
+ const rows = app.db.select().from(aiUserFetchEventsHourly).where(userFetchWhere).orderBy(desc33(aiUserFetchEventsHourly.tsHour)).limit(limit).all();
80155
80310
  for (const r of rows) {
80156
80311
  events.push({
80157
80312
  kind: TrafficEventKinds["ai-user-fetch"],
@@ -80204,7 +80359,7 @@ async function trafficRoutes(app, opts) {
80204
80359
  point.aiReferralHits = Number(row.hits);
80205
80360
  point.aiReferralLandedHits = Number(row.landed);
80206
80361
  }
80207
- const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(desc32(aiReferralEventsHourly.tsHour)).limit(limit).all();
80362
+ const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(desc33(aiReferralEventsHourly.tsHour)).limit(limit).all();
80208
80363
  for (const r of rows) {
80209
80364
  const counts2 = aiReferralClassCounts(r.sessionsOrHits, r.paidSessionsOrHits, r.organicSessionsOrHits);
80210
80365
  events.push({
@@ -80473,7 +80628,7 @@ var reportSweepsCheck = {
80473
80628
  };
80474
80629
 
80475
80630
  // ../api-routes/src/doctor/checks/report-models.ts
80476
- import { and as and59, eq as eq67, gte as gte18, inArray as inArray27, lte as lte19 } from "drizzle-orm";
80631
+ import { and as and59, eq as eq67, gte as gte18, inArray as inArray28, lte as lte19 } from "drizzle-orm";
80477
80632
  var reportModelsCheck = {
80478
80633
  id: "report.models",
80479
80634
  category: CheckCategories.providers,
@@ -80488,7 +80643,7 @@ var reportModelsCheck = {
80488
80643
  const months = reportMonths.flatMap((month) => {
80489
80644
  const bounds = calendarMonthBounds(month);
80490
80645
  const previous = new Date(Date.parse(bounds.since) - 1).toISOString().slice(0, 7);
80491
- const observations = ctx.db.select({ provider: querySnapshots.provider, model: querySnapshots.model, at: runs.createdAt }).from(querySnapshots).innerJoin(runs, eq67(runs.id, querySnapshots.runId)).where(and59(eq67(runs.projectId, ctx.project.id), eq67(runs.kind, RunKinds["answer-visibility"]), inArray27(runs.status, [RunStatuses.completed, RunStatuses.partial]), notProbeRun(), gte18(runs.createdAt, bounds.since), lte19(runs.createdAt, bounds.until))).all();
80646
+ const observations = ctx.db.select({ provider: querySnapshots.provider, model: querySnapshots.model, at: runs.createdAt }).from(querySnapshots).innerJoin(runs, eq67(runs.id, querySnapshots.runId)).where(and59(eq67(runs.projectId, ctx.project.id), eq67(runs.kind, RunKinds["answer-visibility"]), inArray28(runs.status, [RunStatuses.completed, RunStatuses.partial]), notProbeRun(), gte18(runs.createdAt, bounds.since), lte19(runs.createdAt, bounds.until))).all();
80492
80647
  return readVisibilityContinuity(ctx.db, ctx.project.name, { from: previous, to: month }).map(({ frame, continuity: continuity2 }) => ({
80493
80648
  month,
80494
80649
  previousMonth: previous,
@@ -81565,7 +81720,7 @@ var ga4ConnectionCheck = {
81565
81720
  var GA_AUTH_CHECKS = [ga4ConnectionCheck];
81566
81721
 
81567
81722
  // ../api-routes/src/doctor/checks/data-freshness.ts
81568
- import { and as and62, desc as desc33, eq as eq73, inArray as inArray28 } from "drizzle-orm";
81723
+ import { and as and62, desc as desc34, eq as eq73, inArray as inArray29 } from "drizzle-orm";
81569
81724
  var GA_DATA_AGING_DAYS = 3;
81570
81725
  var GA_DATA_STALE_DAYS = 5;
81571
81726
  var GSC_DATA_AGING_DAYS = 5;
@@ -81593,7 +81748,7 @@ function skipped(code, summary3) {
81593
81748
  return { status: CheckStatuses.skipped, code, summary: summary3, remediation: null };
81594
81749
  }
81595
81750
  function lastSyncAgeDays(ctx, kinds) {
81596
- const row = ctx.db.select({ createdAt: runs.createdAt }).from(runs).where(and62(eq73(runs.projectId, ctx.project.id), inArray28(runs.kind, kinds), eq73(runs.status, "completed"))).orderBy(desc33(runs.createdAt)).limit(1).get();
81751
+ const row = ctx.db.select({ createdAt: runs.createdAt }).from(runs).where(and62(eq73(runs.projectId, ctx.project.id), inArray29(runs.kind, kinds), eq73(runs.status, "completed"))).orderBy(desc34(runs.createdAt)).limit(1).get();
81597
81752
  if (!row?.createdAt) return null;
81598
81753
  const age = Math.floor((Date.now() - Date.parse(row.createdAt)) / DAY_MS2);
81599
81754
  return Number.isFinite(age) ? age : null;
@@ -81689,7 +81844,7 @@ var gaRecentDataCheck = {
81689
81844
  const connection = gaConnected(ctx);
81690
81845
  if (connection === "store-unavailable") return skipped("ga.data.store-unavailable", "No GA4 credential store configured for this deployment.");
81691
81846
  if (connection === "not-connected") return skipped("ga.data.not-connected", "GA4 is not connected for this project.");
81692
- const newest = ctx.db.select({ date: gaDailyTotals.date }).from(gaDailyTotals).where(eq73(gaDailyTotals.projectId, ctx.project.id)).orderBy(desc33(gaDailyTotals.date)).limit(1).get();
81847
+ const newest = ctx.db.select({ date: gaDailyTotals.date }).from(gaDailyTotals).where(eq73(gaDailyTotals.projectId, ctx.project.id)).orderBy(desc34(gaDailyTotals.date)).limit(1).get();
81693
81848
  return grade(ctx, GA_SPEC, newest?.date);
81694
81849
  }
81695
81850
  };
@@ -81706,7 +81861,7 @@ var gscRecentDataCheck = {
81706
81861
  }
81707
81862
  const watermark = ctx.db.select({ dataThroughDate: gscDataWatermarks.dataThroughDate }).from(gscDataWatermarks).where(eq73(gscDataWatermarks.projectId, ctx.project.id)).get();
81708
81863
  if (watermark?.dataThroughDate) return grade(ctx, GSC_SPEC, watermark.dataThroughDate);
81709
- const newest = ctx.db.select({ date: gscDailyTotals.date }).from(gscDailyTotals).where(eq73(gscDailyTotals.projectId, ctx.project.id)).orderBy(desc33(gscDailyTotals.date)).limit(1).get();
81864
+ const newest = ctx.db.select({ date: gscDailyTotals.date }).from(gscDailyTotals).where(eq73(gscDailyTotals.projectId, ctx.project.id)).orderBy(desc34(gscDailyTotals.date)).limit(1).get();
81710
81865
  return grade(ctx, GSC_SPEC, newest?.date);
81711
81866
  }
81712
81867
  };
@@ -82962,7 +83117,7 @@ var RUNTIME_STATE_CHECKS = [
82962
83117
  ];
82963
83118
 
82964
83119
  // ../api-routes/src/doctor/checks/traffic-source.ts
82965
- import { and as and65, eq as eq77, gte as gte19, inArray as inArray29, ne as ne14, sql as sql28 } from "drizzle-orm";
83120
+ import { and as and65, eq as eq77, gte as gte19, inArray as inArray30, ne as ne14, sql as sql28 } from "drizzle-orm";
82966
83121
  var RECENT_DATA_WARN_DAYS = 7;
82967
83122
  var RECENT_DATA_FAIL_DAYS = 30;
82968
83123
  function isCloudflareDirectPush(source) {
@@ -83110,7 +83265,7 @@ var recentDataCheck = {
83110
83265
  ctx.db.select({ total: sql28`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
83111
83266
  and65(
83112
83267
  eq77(crawlerEventsHourly.projectId, ctx.project.id),
83113
- inArray29(crawlerEventsHourly.sourceId, activeSourceIds),
83268
+ inArray30(crawlerEventsHourly.sourceId, activeSourceIds),
83114
83269
  gte19(crawlerEventsHourly.tsHour, warnCutoff)
83115
83270
  )
83116
83271
  ).get()?.total ?? 0
@@ -83119,7 +83274,7 @@ var recentDataCheck = {
83119
83274
  ctx.db.select({ total: sql28`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
83120
83275
  and65(
83121
83276
  eq77(aiReferralEventsHourly.projectId, ctx.project.id),
83122
- inArray29(aiReferralEventsHourly.sourceId, activeSourceIds),
83277
+ inArray30(aiReferralEventsHourly.sourceId, activeSourceIds),
83123
83278
  gte19(aiReferralEventsHourly.tsHour, warnCutoff)
83124
83279
  )
83125
83280
  ).get()?.total ?? 0
@@ -83128,7 +83283,7 @@ var recentDataCheck = {
83128
83283
  ctx.db.select({ total: sql28`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
83129
83284
  and65(
83130
83285
  eq77(aiUserFetchEventsHourly.projectId, ctx.project.id),
83131
- inArray29(aiUserFetchEventsHourly.sourceId, activeSourceIds),
83286
+ inArray30(aiUserFetchEventsHourly.sourceId, activeSourceIds),
83132
83287
  gte19(aiUserFetchEventsHourly.tsHour, warnCutoff)
83133
83288
  )
83134
83289
  ).get()?.total ?? 0
@@ -83154,7 +83309,7 @@ var recentDataCheck = {
83154
83309
  ctx.db.select({ total: sql28`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
83155
83310
  and65(
83156
83311
  eq77(crawlerEventsHourly.projectId, ctx.project.id),
83157
- inArray29(crawlerEventsHourly.sourceId, activeSourceIds),
83312
+ inArray30(crawlerEventsHourly.sourceId, activeSourceIds),
83158
83313
  gte19(crawlerEventsHourly.tsHour, failCutoff)
83159
83314
  )
83160
83315
  ).get()?.total ?? 0
@@ -83163,7 +83318,7 @@ var recentDataCheck = {
83163
83318
  ctx.db.select({ total: sql28`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
83164
83319
  and65(
83165
83320
  eq77(aiReferralEventsHourly.projectId, ctx.project.id),
83166
- inArray29(aiReferralEventsHourly.sourceId, activeSourceIds),
83321
+ inArray30(aiReferralEventsHourly.sourceId, activeSourceIds),
83167
83322
  gte19(aiReferralEventsHourly.tsHour, failCutoff)
83168
83323
  )
83169
83324
  ).get()?.total ?? 0
@@ -83172,7 +83327,7 @@ var recentDataCheck = {
83172
83327
  ctx.db.select({ total: sql28`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
83173
83328
  and65(
83174
83329
  eq77(aiUserFetchEventsHourly.projectId, ctx.project.id),
83175
- inArray29(aiUserFetchEventsHourly.sourceId, activeSourceIds),
83330
+ inArray30(aiUserFetchEventsHourly.sourceId, activeSourceIds),
83176
83331
  gte19(aiUserFetchEventsHourly.tsHour, failCutoff)
83177
83332
  )
83178
83333
  ).get()?.total ?? 0
@@ -84179,7 +84334,7 @@ async function doctorRoutes(app, opts) {
84179
84334
 
84180
84335
  // ../api-routes/src/discovery/routes.ts
84181
84336
  import crypto47 from "crypto";
84182
- import { and as and66, desc as desc34, eq as eq78, gte as gte20, inArray as inArray30, isNull as isNull14, or as or17 } from "drizzle-orm";
84337
+ import { and as and66, desc as desc35, eq as eq78, gte as gte20, inArray as inArray31, isNull as isNull14, or as or17 } from "drizzle-orm";
84183
84338
  var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
84184
84339
  async function discoveryRoutes(app, opts) {
84185
84340
  app.post("/projects/:name/discover/run", async (request, reply) => {
@@ -84234,13 +84389,13 @@ async function discoveryRoutes(app, opts) {
84234
84389
  // must never reuse another set's session. Null (= Gemini-only
84235
84390
  // default, including explicit ['gemini']) matches legacy rows.
84236
84391
  seedProviders == null ? isNull14(discoverySessions.seedProviders) : eq78(discoverySessions.seedProviders, seedProviders),
84237
- inArray30(discoverySessions.status, [
84392
+ inArray31(discoverySessions.status, [
84238
84393
  DiscoverySessionStatuses.queued,
84239
84394
  DiscoverySessionStatuses.seeding,
84240
84395
  DiscoverySessionStatuses.probing
84241
84396
  ]),
84242
84397
  gte20(discoverySessions.createdAt, ageFloorIso)
84243
- )).orderBy(desc34(discoverySessions.createdAt)).get();
84398
+ )).orderBy(desc35(discoverySessions.createdAt)).get();
84244
84399
  if (existing && existing.runId) {
84245
84400
  return { reused: true, sessionId: existing.id, runId: existing.runId };
84246
84401
  }
@@ -84309,7 +84464,7 @@ async function discoveryRoutes(app, opts) {
84309
84464
  const project = resolveProject(app.db, request.params.name);
84310
84465
  const parsedLimit = parseInt(request.query.limit ?? "", 10);
84311
84466
  const limit = Number.isNaN(parsedLimit) || parsedLimit <= 0 ? 50 : parsedLimit;
84312
- const rows = app.db.select().from(discoverySessions).where(eq78(discoverySessions.projectId, project.id)).orderBy(desc34(discoverySessions.createdAt)).limit(limit).all();
84467
+ const rows = app.db.select().from(discoverySessions).where(eq78(discoverySessions.projectId, project.id)).orderBy(desc35(discoverySessions.createdAt)).limit(limit).all();
84313
84468
  return reply.send(rows.map(serializeSession));
84314
84469
  }
84315
84470
  );
@@ -84933,7 +85088,7 @@ function dedupeStrings(input) {
84933
85088
 
84934
85089
  // ../api-routes/src/technical-aeo.ts
84935
85090
  import crypto49 from "crypto";
84936
- import { and as and67, asc as asc14, count as count2, desc as desc35, eq as eq80, inArray as inArray31, isNotNull as isNotNull8, isNull as isNull15, lt as lt13, or as or18, sql as sql29 } from "drizzle-orm";
85091
+ import { and as and67, asc as asc14, count as count2, desc as desc36, eq as eq80, inArray as inArray32, isNotNull as isNotNull8, isNull as isNull15, lt as lt13, or as or18, sql as sql29 } from "drizzle-orm";
84937
85092
  import { alias } from "drizzle-orm/sqlite-core";
84938
85093
  var FETCHED_SITE_CRAWL_STATES = /* @__PURE__ */ new Set([
84939
85094
  ...SiteCrawlFetchedStates,
@@ -85258,11 +85413,11 @@ async function technicalAeoRoutes(app, opts) {
85258
85413
  eq80(siteCrawlSnapshots.projectId, projectId),
85259
85414
  eq80(runs.projectId, projectId),
85260
85415
  eq80(runs.kind, RunKinds["site-audit"]),
85261
- inArray31(runs.status, SURFACEABLE_STATUSES),
85416
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85262
85417
  notProbeRun()
85263
85418
  ];
85264
85419
  if (runId) filters.push(eq80(siteCrawlSnapshots.runId, runId));
85265
- return app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(...filters)).orderBy(desc35(siteCrawlSnapshots.createdAt), desc35(siteCrawlSnapshots.runId)).limit(1).get();
85420
+ return app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(...filters)).orderBy(desc36(siteCrawlSnapshots.createdAt), desc36(siteCrawlSnapshots.runId)).limit(1).get();
85266
85421
  };
85267
85422
  const detailScopeFor = (projectId, snapshot) => snapshot.detailsAvailable && snapshot.attemptId ? { projectId, runId: snapshot.runId, attemptId: snapshot.attemptId } : null;
85268
85423
  const completenessOf = (snapshot) => ({
@@ -85289,7 +85444,7 @@ async function technicalAeoRoutes(app, opts) {
85289
85444
  eq80(runs.id, runId),
85290
85445
  eq80(runs.projectId, projectId),
85291
85446
  eq80(runs.kind, RunKinds["site-audit"]),
85292
- inArray31(runs.status, SURFACEABLE_STATUSES),
85447
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85293
85448
  notProbeRun()
85294
85449
  )).limit(1).get());
85295
85450
  const assertKnownAuditRun = (projectId, runId) => {
@@ -85299,7 +85454,7 @@ async function technicalAeoRoutes(app, opts) {
85299
85454
  eq80(siteAuditSnapshots.projectId, projectId),
85300
85455
  eq80(runs.projectId, projectId),
85301
85456
  eq80(runs.kind, RunKinds["site-audit"]),
85302
- inArray31(runs.status, SURFACEABLE_STATUSES),
85457
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85303
85458
  notProbeRun()
85304
85459
  )).limit(1).get());
85305
85460
  const emptyCrawlSummary = (projectName, legacyAuditAvailable) => ({
@@ -85323,17 +85478,17 @@ async function technicalAeoRoutes(app, opts) {
85323
85478
  eq80(siteAuditSnapshots.projectId, project.id),
85324
85479
  eq80(runs.projectId, project.id),
85325
85480
  eq80(runs.kind, RunKinds["site-audit"]),
85326
- inArray31(runs.status, SURFACEABLE_STATUSES),
85481
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85327
85482
  notProbeRun()
85328
85483
  ];
85329
85484
  const targetFilters = request.query.runId ? [...baseFilters, eq80(siteAuditSnapshots.runId, request.query.runId)] : baseFilters;
85330
- const latest = app.db.select({ snap: siteAuditSnapshots, runStatus: runs.status }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...targetFilters)).orderBy(desc35(siteAuditSnapshots.createdAt)).limit(1).get();
85485
+ const latest = app.db.select({ snap: siteAuditSnapshots, runStatus: runs.status }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...targetFilters)).orderBy(desc36(siteAuditSnapshots.createdAt)).limit(1).get();
85331
85486
  if (!latest) {
85332
85487
  if (request.query.runId) throw notFound("Site audit run", request.query.runId);
85333
85488
  return emptyScore(project.name);
85334
85489
  }
85335
85490
  const snap = latest.snap;
85336
- const previous = app.db.select({ snap: siteAuditSnapshots }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...baseFilters, lt13(siteAuditSnapshots.createdAt, snap.createdAt))).orderBy(desc35(siteAuditSnapshots.createdAt)).limit(1).get()?.snap ?? null;
85491
+ const previous = app.db.select({ snap: siteAuditSnapshots }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...baseFilters, lt13(siteAuditSnapshots.createdAt, snap.createdAt))).orderBy(desc36(siteAuditSnapshots.createdAt)).limit(1).get()?.snap ?? null;
85337
85492
  const deltaScore = previous ? snap.aggregateScore - previous.aggregateScore : null;
85338
85493
  const trend = deltaScore == null ? null : deltaScore > 0 ? SiteAuditTrendDirections.up : deltaScore < 0 ? SiteAuditTrendDirections.down : SiteAuditTrendDirections.flat;
85339
85494
  return {
@@ -85363,11 +85518,11 @@ async function technicalAeoRoutes(app, opts) {
85363
85518
  eq80(siteAuditSnapshots.projectId, project.id),
85364
85519
  eq80(runs.projectId, project.id),
85365
85520
  eq80(runs.kind, RunKinds["site-audit"]),
85366
- inArray31(runs.status, SURFACEABLE_STATUSES),
85521
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85367
85522
  notProbeRun()
85368
85523
  ];
85369
85524
  if (request.query.runId) targetFilters.push(eq80(siteAuditSnapshots.runId, request.query.runId));
85370
- const latest = app.db.select({ runId: siteAuditSnapshots.runId, auditedAt: siteAuditSnapshots.auditedAt }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...targetFilters)).orderBy(desc35(siteAuditSnapshots.createdAt)).limit(1).get();
85525
+ const latest = app.db.select({ runId: siteAuditSnapshots.runId, auditedAt: siteAuditSnapshots.auditedAt }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...targetFilters)).orderBy(desc36(siteAuditSnapshots.createdAt)).limit(1).get();
85371
85526
  if (!latest && request.query.runId) {
85372
85527
  throw notFound("Site audit run", request.query.runId);
85373
85528
  }
@@ -85382,7 +85537,7 @@ async function technicalAeoRoutes(app, opts) {
85382
85537
  const total = totalRow?.value ?? 0;
85383
85538
  const limit = parsePositiveInt(request.query.limit, 100, 500);
85384
85539
  const offset = parsePositiveInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER);
85385
- const orderBy = request.query.sort === "score-desc" ? desc35(siteAuditPages.overallScore) : request.query.sort === "url" ? asc14(siteAuditPages.url) : asc14(siteAuditPages.overallScore);
85540
+ const orderBy = request.query.sort === "score-desc" ? desc36(siteAuditPages.overallScore) : request.query.sort === "url" ? asc14(siteAuditPages.url) : asc14(siteAuditPages.overallScore);
85386
85541
  const rows = app.db.select().from(siteAuditPages).where(where).orderBy(orderBy).limit(limit).offset(offset).all();
85387
85542
  const pages = rows.map((row) => ({
85388
85543
  url: row.url,
@@ -85405,9 +85560,9 @@ async function technicalAeoRoutes(app, opts) {
85405
85560
  eq80(siteAuditSnapshots.projectId, project.id),
85406
85561
  eq80(runs.projectId, project.id),
85407
85562
  eq80(runs.kind, RunKinds["site-audit"]),
85408
- inArray31(runs.status, SURFACEABLE_STATUSES),
85563
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85409
85564
  notProbeRun()
85410
- )).orderBy(desc35(siteAuditSnapshots.createdAt)).limit(limit).all();
85565
+ )).orderBy(desc36(siteAuditSnapshots.createdAt)).limit(limit).all();
85411
85566
  return { project: project.name, points: rows.reverse() };
85412
85567
  });
85413
85568
  app.get("/projects/:name/technical-aeo/crawl", async (request) => {
@@ -85713,8 +85868,8 @@ async function technicalAeoRoutes(app, opts) {
85713
85868
  eq80(siteCrawlEdges.internal, true),
85714
85869
  isNotNull8(siteCrawlEdges.targetNodeKey),
85715
85870
  or18(
85716
- inArray31(siteCrawlEdges.sourceNodeKey, frontier),
85717
- inArray31(siteCrawlEdges.targetNodeKey, frontier)
85871
+ inArray32(siteCrawlEdges.sourceNodeKey, frontier),
85872
+ inArray32(siteCrawlEdges.targetNodeKey, frontier)
85718
85873
  )
85719
85874
  )).orderBy(asc14(siteCrawlEdges.edgeKey)).limit(maxEdges + maxNodes + 1).all();
85720
85875
  if (candidates.length > maxEdges + maxNodes) queryTruncated = true;
@@ -85751,7 +85906,7 @@ async function technicalAeoRoutes(app, opts) {
85751
85906
  eq80(siteCrawlPages.projectId, scope.projectId),
85752
85907
  eq80(siteCrawlPages.runId, scope.runId),
85753
85908
  eq80(siteCrawlPages.attemptId, scope.attemptId),
85754
- inArray31(siteCrawlPages.nodeKey, nodeKeys)
85909
+ inArray32(siteCrawlPages.nodeKey, nodeKeys)
85755
85910
  )).all();
85756
85911
  const persistedNodeKeys = new Set(pageRows.map((row) => row.nodeKey));
85757
85912
  const outermostNodeKeys = pageRows.filter((row) => distances.get(row.nodeKey) === hops).map((row) => row.nodeKey);
@@ -85761,8 +85916,8 @@ async function technicalAeoRoutes(app, opts) {
85761
85916
  eq80(siteCrawlEdges.attemptId, scope.attemptId),
85762
85917
  eq80(siteCrawlEdges.internal, true),
85763
85918
  isNotNull8(siteCrawlEdges.targetNodeKey),
85764
- inArray31(siteCrawlEdges.sourceNodeKey, outermostNodeKeys),
85765
- inArray31(siteCrawlEdges.targetNodeKey, outermostNodeKeys)
85919
+ inArray32(siteCrawlEdges.sourceNodeKey, outermostNodeKeys),
85920
+ inArray32(siteCrawlEdges.targetNodeKey, outermostNodeKeys)
85766
85921
  )).limit(1).get();
85767
85922
  if (omittedOutermostEdge && !seenEdgeKeys.has(omittedOutermostEdge.edgeKey)) {
85768
85923
  omittedEdgeKeys.add(omittedOutermostEdge.edgeKey);
@@ -85865,7 +86020,7 @@ async function technicalAeoRoutes(app, opts) {
85865
86020
  eq80(siteCrawlEdges.followable, true),
85866
86021
  eq80(siteCrawlEdges.relation, "anchor"),
85867
86022
  isNotNull8(siteCrawlEdges.targetNodeKey),
85868
- inArray31(siteCrawlEdges.sourceNodeKey, frontier)
86023
+ inArray32(siteCrawlEdges.sourceNodeKey, frontier)
85869
86024
  )).orderBy(asc14(siteCrawlEdges.edgeKey)).limit(SITE_HEALTH_PATH_MAX_VISITED_NODES + 1).all();
85870
86025
  if (candidates.length > SITE_HEALTH_PATH_MAX_VISITED_NODES) truncated = true;
85871
86026
  const candidateTargetKeys = [...new Set(candidates.map((edge) => edge.targetNodeKey).filter((nodeKey) => nodeKey != null))];
@@ -85873,7 +86028,7 @@ async function technicalAeoRoutes(app, opts) {
85873
86028
  eq80(siteCrawlPages.projectId, scope.projectId),
85874
86029
  eq80(siteCrawlPages.runId, scope.runId),
85875
86030
  eq80(siteCrawlPages.attemptId, scope.attemptId),
85876
- inArray31(siteCrawlPages.nodeKey, candidateTargetKeys)
86031
+ inArray32(siteCrawlPages.nodeKey, candidateTargetKeys)
85877
86032
  )).all().map((row) => row.nodeKey));
85878
86033
  const next = /* @__PURE__ */ new Set();
85879
86034
  for (const edge of candidates.slice(0, SITE_HEALTH_PATH_MAX_VISITED_NODES)) {
@@ -85919,7 +86074,7 @@ async function technicalAeoRoutes(app, opts) {
85919
86074
  eq80(siteCrawlPages.projectId, scope.projectId),
85920
86075
  eq80(siteCrawlPages.runId, scope.runId),
85921
86076
  eq80(siteCrawlPages.attemptId, scope.attemptId),
85922
- inArray31(siteCrawlPages.nodeKey, pathKeys)
86077
+ inArray32(siteCrawlPages.nodeKey, pathKeys)
85923
86078
  )).all();
85924
86079
  const pageByKey = new Map(pathRows.map((row) => [row.nodeKey, row]));
85925
86080
  const pathDetection = templateDetectionOf(snapshot.templateDetection);
@@ -85955,7 +86110,7 @@ async function technicalAeoRoutes(app, opts) {
85955
86110
  eq80(siteCrawlSnapshots.complete, true),
85956
86111
  notProbeRun()
85957
86112
  ];
85958
- const afterTarget = request.query.toRunId ? resolveCrawl(project.id, request.query.toRunId) : app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(...completeSnapshotFilters)).orderBy(desc35(siteCrawlSnapshots.createdAt), desc35(siteCrawlSnapshots.runId)).limit(1).get();
86113
+ const afterTarget = request.query.toRunId ? resolveCrawl(project.id, request.query.toRunId) : app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(...completeSnapshotFilters)).orderBy(desc36(siteCrawlSnapshots.createdAt), desc36(siteCrawlSnapshots.runId)).limit(1).get();
85959
86114
  if (request.query.toRunId && !afterTarget) throw notFound("Site crawl run", request.query.toRunId);
85960
86115
  const beforeTarget = request.query.fromRunId ? resolveCrawl(project.id, request.query.fromRunId) : afterTarget ? app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(
85961
86116
  ...completeSnapshotFilters,
@@ -85966,7 +86121,7 @@ async function technicalAeoRoutes(app, opts) {
85966
86121
  lt13(siteCrawlSnapshots.runId, afterTarget.snapshot.runId)
85967
86122
  )
85968
86123
  )
85969
- )).orderBy(desc35(siteCrawlSnapshots.createdAt), desc35(siteCrawlSnapshots.runId)).limit(1).get() : void 0;
86124
+ )).orderBy(desc36(siteCrawlSnapshots.createdAt), desc36(siteCrawlSnapshots.runId)).limit(1).get() : void 0;
85970
86125
  if (request.query.fromRunId && !beforeTarget) throw notFound("Site crawl run", request.query.fromRunId);
85971
86126
  if (!afterTarget) {
85972
86127
  const latestCrawl = resolveCrawl(project.id);
@@ -86211,14 +86366,14 @@ async function technicalAeoRoutes(app, opts) {
86211
86366
  eq80(siteCrawlPages.projectId, scope.projectId),
86212
86367
  eq80(siteCrawlPages.runId, scope.runId),
86213
86368
  eq80(siteCrawlPages.attemptId, scope.attemptId),
86214
- inArray31(siteCrawlPages.nodeKey, pageKeys)
86369
+ inArray32(siteCrawlPages.nodeKey, pageKeys)
86215
86370
  )).all();
86216
86371
  const edgeRowsFor = (scope) => linkKeys.length === 0 ? [] : app.db.select().from(siteCrawlEdges).where(and67(
86217
86372
  eq80(siteCrawlEdges.projectId, scope.projectId),
86218
86373
  eq80(siteCrawlEdges.runId, scope.runId),
86219
86374
  eq80(siteCrawlEdges.attemptId, scope.attemptId),
86220
86375
  eq80(siteCrawlEdges.internal, true),
86221
- inArray31(siteCrawlEdges.edgeKey, linkKeys)
86376
+ inArray32(siteCrawlEdges.edgeKey, linkKeys)
86222
86377
  )).all();
86223
86378
  const beforePages = new Map(pageRowsFor(beforeScope).map((row) => [row.nodeKey, mapCrawlPage(row)]));
86224
86379
  const afterPages = new Map(pageRowsFor(afterScope).map((row) => [row.nodeKey, mapCrawlPage(row)]));
@@ -86356,7 +86511,7 @@ async function technicalAeoRoutes(app, opts) {
86356
86511
  const healthState = parseSiteHealthState(request.query.healthState);
86357
86512
  const limit = parseBoundedLimit(request.query.limit, 100, 200);
86358
86513
  const offset = decodeCursor(request.query.cursor);
86359
- const orderBy = request.query.sort === "score-desc" ? [desc35(siteCrawlPages.auditScore), asc14(siteCrawlPages.nodeKey)] : request.query.sort === "score-asc" ? [asc14(siteCrawlPages.auditScore), asc14(siteCrawlPages.nodeKey)] : request.query.sort === "path" ? [asc14(siteCrawlPages.path), asc14(siteCrawlPages.nodeKey)] : [asc14(siteCrawlPages.url), asc14(siteCrawlPages.nodeKey)];
86514
+ const orderBy = request.query.sort === "score-desc" ? [desc36(siteCrawlPages.auditScore), asc14(siteCrawlPages.nodeKey)] : request.query.sort === "score-asc" ? [asc14(siteCrawlPages.auditScore), asc14(siteCrawlPages.nodeKey)] : request.query.sort === "path" ? [asc14(siteCrawlPages.path), asc14(siteCrawlPages.nodeKey)] : [asc14(siteCrawlPages.url), asc14(siteCrawlPages.nodeKey)];
86360
86515
  let healthStateFilter = null;
86361
86516
  if (healthState) {
86362
86517
  const legacyRow = app.db.select({ id: siteCrawlPages.id }).from(siteCrawlPages).where(and67(
@@ -86669,15 +86824,15 @@ async function technicalAeoRoutes(app, opts) {
86669
86824
  eq80(runs.projectId, project.id),
86670
86825
  eq80(runs.kind, RunKinds["site-audit"]),
86671
86826
  notProbeRun()
86672
- )).orderBy(desc35(runs.createdAt), desc35(runs.id)).limit(limit).all();
86827
+ )).orderBy(desc36(runs.createdAt), desc36(runs.id)).limit(limit).all();
86673
86828
  const runIds = rows.map((row) => row.runId);
86674
86829
  const crawlRunIds = new Set(runIds.length === 0 ? [] : app.db.select({ runId: siteCrawlSnapshots.runId }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(
86675
86830
  eq80(siteCrawlSnapshots.projectId, project.id),
86676
86831
  eq80(runs.projectId, project.id),
86677
86832
  eq80(runs.kind, RunKinds["site-audit"]),
86678
- inArray31(runs.status, SURFACEABLE_STATUSES),
86833
+ inArray32(runs.status, SURFACEABLE_STATUSES),
86679
86834
  notProbeRun(),
86680
- inArray31(siteCrawlSnapshots.runId, runIds)
86835
+ inArray32(siteCrawlSnapshots.runId, runIds)
86681
86836
  )).all().map((row) => row.runId));
86682
86837
  return {
86683
86838
  project: project.name,
@@ -86700,7 +86855,7 @@ async function technicalAeoRoutes(app, opts) {
86700
86855
  const attempt = app.db.select().from(siteCrawlAttempts).where(and67(
86701
86856
  eq80(siteCrawlAttempts.projectId, project.id),
86702
86857
  eq80(siteCrawlAttempts.runId, run.id)
86703
- )).orderBy(desc35(siteCrawlAttempts.attemptNumber), desc35(siteCrawlAttempts.updatedAt)).limit(1).get();
86858
+ )).orderBy(desc36(siteCrawlAttempts.attemptNumber), desc36(siteCrawlAttempts.updatedAt)).limit(1).get();
86704
86859
  const persistedLayout = attempt ? app.db.select().from(siteCrawlGraphLayouts).where(and67(
86705
86860
  eq80(siteCrawlGraphLayouts.projectId, project.id),
86706
86861
  eq80(siteCrawlGraphLayouts.runId, run.id),
@@ -86747,7 +86902,7 @@ async function technicalAeoRoutes(app, opts) {
86747
86902
  const attempt = tx.select().from(siteCrawlAttempts).where(and67(
86748
86903
  eq80(siteCrawlAttempts.projectId, project.id),
86749
86904
  eq80(siteCrawlAttempts.runId, run.id)
86750
- )).orderBy(desc35(siteCrawlAttempts.attemptNumber), desc35(siteCrawlAttempts.updatedAt)).limit(1).get();
86905
+ )).orderBy(desc36(siteCrawlAttempts.attemptNumber), desc36(siteCrawlAttempts.updatedAt)).limit(1).get();
86751
86906
  const state = run.status === RunStatuses.queued ? "waiting" : run.status === RunStatuses.running ? "collecting" : "terminal";
86752
86907
  const base = {
86753
86908
  project: project.name,
@@ -86817,7 +86972,7 @@ async function technicalAeoRoutes(app, opts) {
86817
86972
  )).where(and67(
86818
86973
  eq80(runs.projectId, project.id),
86819
86974
  eq80(runs.kind, RunKinds["site-audit"]),
86820
- inArray31(runs.status, [RunStatuses.queued, RunStatuses.running])
86975
+ inArray32(runs.status, [RunStatuses.queued, RunStatuses.running])
86821
86976
  )).get();
86822
86977
  if (existing) {
86823
86978
  if (existing.identityKey === identityKey) {
@@ -86871,7 +87026,7 @@ async function technicalAeoRoutes(app, opts) {
86871
87026
  // ../api-routes/src/research.ts
86872
87027
  import crypto50 from "crypto";
86873
87028
  import { z as z5 } from "zod";
86874
- import { and as and68, count as count3, desc as desc36, eq as eq81, gte as gte21, lt as lt14, or as or19, sql as sql30 } from "drizzle-orm";
87029
+ import { and as and68, count as count3, desc as desc37, eq as eq81, gte as gte21, lt as lt14, or as or19, sql as sql30 } from "drizzle-orm";
86875
87030
  var sameLocation = (a, b) => a.label === b.label && a.city === b.city && a.region === b.region && a.country === b.country && a.timezone === b.timezone;
86876
87031
  var BATCH_RECEIPT_PREFIX = "__canonry_research_batch__:";
86877
87032
  async function researchRoutes(app, opts) {
@@ -87042,7 +87197,7 @@ async function researchRoutes(app, opts) {
87042
87197
  const rows = app.db.select().from(researchRuns).where(and68(
87043
87198
  eq81(researchRuns.projectId, project.id),
87044
87199
  cursor ? or19(lt14(researchRuns.createdAt, cursor.createdAt), and68(eq81(researchRuns.createdAt, cursor.createdAt), lt14(researchRuns.id, cursor.id))) : void 0
87045
- )).orderBy(desc36(researchRuns.createdAt), desc36(researchRuns.id)).limit(limit + 1).all();
87200
+ )).orderBy(desc37(researchRuns.createdAt), desc37(researchRuns.id)).limit(limit + 1).all();
87046
87201
  const runs2 = rows.slice(0, limit).map(serializeRun);
87047
87202
  const last = runs2.at(-1);
87048
87203
  const nextCursor = rows.length > limit && last ? Buffer.from(JSON.stringify({ projectId: project.id, createdAt: last.createdAt, id: last.id })).toString("base64url") : null;
@@ -87223,7 +87378,7 @@ function utcDayBounds(now) {
87223
87378
  }
87224
87379
 
87225
87380
  // ../api-routes/src/snapshot-competitor-refresh.ts
87226
- import { and as and69, eq as eq82, inArray as inArray32 } from "drizzle-orm";
87381
+ import { and as and69, eq as eq82, inArray as inArray33 } from "drizzle-orm";
87227
87382
  var SNAPSHOT_BATCH_SIZE = 500;
87228
87383
  function backfillProjectAnswerMentions(db, projectId, opts) {
87229
87384
  const isDryRun = opts?.dryRun === true;
@@ -87267,7 +87422,7 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
87267
87422
  competitorOverlap: querySnapshots.competitorOverlap,
87268
87423
  recommendedCompetitors: querySnapshots.recommendedCompetitors,
87269
87424
  rawResponse: querySnapshots.rawResponse
87270
- }).from(querySnapshots).where(inArray32(querySnapshots.runId, batchRunIds)).all();
87425
+ }).from(querySnapshots).where(inArray33(querySnapshots.runId, batchRunIds)).all();
87271
87426
  const pendingUpdates = [];
87272
87427
  for (const snapshot of snapshotRows) {
87273
87428
  if (competitorFieldsOnly && snapshot.answerText == null) continue;
@@ -88323,7 +88478,7 @@ var IntelligenceService = class {
88323
88478
  this.db.select({ one: sql31`1` }).from(querySnapshots).where(eq84(querySnapshots.runId, runs.id))
88324
88479
  )
88325
88480
  )
88326
- ).orderBy(desc37(runs.finishedAt), desc37(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
88481
+ ).orderBy(desc38(runs.finishedAt), desc38(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
88327
88482
  const trackedCompetitors = this.loadTrackedCompetitors(projectId);
88328
88483
  const currentRun = this.buildRunData(
88329
88484
  runId,
@@ -88442,10 +88597,10 @@ var IntelligenceService = class {
88442
88597
  buildGbpLocationSignals(projectId, locationName, displayName, fallbackDate) {
88443
88598
  const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and71(eq84(gbpDailyMetrics.projectId, projectId), eq84(gbpDailyMetrics.locationName, locationName))).all();
88444
88599
  const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and71(eq84(gbpPlaceActions.projectId, projectId), eq84(gbpPlaceActions.locationName, locationName))).all();
88445
- const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and71(eq84(gbpLodgingSnapshots.projectId, projectId), eq84(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc37(gbpLodgingSnapshots.syncedAt)).limit(1).get();
88600
+ const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and71(eq84(gbpLodgingSnapshots.projectId, projectId), eq84(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc38(gbpLodgingSnapshots.syncedAt)).limit(1).get();
88446
88601
  const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and71(eq84(gbpLocations.projectId, projectId), eq84(gbpLocations.locationName, locationName))).get();
88447
88602
  const descriptionMissing = !(ownerRow?.description ?? "").trim();
88448
- const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and71(eq84(gbpPlaceDetails.projectId, projectId), eq84(gbpPlaceDetails.locationName, locationName))).orderBy(desc37(gbpPlaceDetails.syncedAt)).limit(1).get();
88603
+ const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and71(eq84(gbpPlaceDetails.projectId, projectId), eq84(gbpPlaceDetails.locationName, locationName))).orderBy(desc38(gbpPlaceDetails.syncedAt)).limit(1).get();
88449
88604
  const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
88450
88605
  const summary3 = buildGbpSummary({
88451
88606
  locationName,
@@ -88652,7 +88807,7 @@ var IntelligenceService = class {
88652
88807
  let wouldDeleteTotal = 0;
88653
88808
  const existingByRunId = /* @__PURE__ */ new Map();
88654
88809
  if (isDryRun && targetRuns.length > 0) {
88655
- const rows = this.db.select({ runId: insights.runId }).from(insights).where(inArray33(insights.runId, targetRuns.map((r) => r.id))).all();
88810
+ const rows = this.db.select({ runId: insights.runId }).from(insights).where(inArray34(insights.runId, targetRuns.map((r) => r.id))).all();
88656
88811
  for (const r of rows) {
88657
88812
  if (r.runId == null) continue;
88658
88813
  existingByRunId.set(r.runId, (existingByRunId.get(r.runId) ?? 0) + 1);
@@ -88707,7 +88862,7 @@ var IntelligenceService = class {
88707
88862
  */
88708
88863
  runIdsWithSnapshots(runIds) {
88709
88864
  if (runIds.length === 0) return /* @__PURE__ */ new Set();
88710
- const rows = this.db.select({ runId: querySnapshots.runId }).from(querySnapshots).where(inArray33(querySnapshots.runId, [...runIds])).groupBy(querySnapshots.runId).all();
88865
+ const rows = this.db.select({ runId: querySnapshots.runId }).from(querySnapshots).where(inArray34(querySnapshots.runId, [...runIds])).groupBy(querySnapshots.runId).all();
88711
88866
  return new Set(rows.map((r) => r.runId));
88712
88867
  }
88713
88868
  /**
@@ -88852,7 +89007,7 @@ var IntelligenceService = class {
88852
89007
  // Defensive — see top of file.
88853
89008
  ne15(runs.trigger, RunTriggers.probe)
88854
89009
  )
88855
- ).orderBy(desc37(runs.createdAt), desc37(runs.id)).limit((RECURRENCE_LOOKBACK_RUNS + 1) * ROWS_PER_GROUP_BUDGET).all();
89010
+ ).orderBy(desc38(runs.createdAt), desc38(runs.id)).limit((RECURRENCE_LOOKBACK_RUNS + 1) * ROWS_PER_GROUP_BUDGET).all();
88856
89011
  const recentGroups = groupRunsByCreatedAt(recentRunRows);
88857
89012
  const recentRunIds = [];
88858
89013
  const recentRunIdToCreatedAt = /* @__PURE__ */ new Map();
@@ -88868,7 +89023,7 @@ var IntelligenceService = class {
88868
89023
  const haveHistory = recentRunIds.length > 0;
88869
89024
  const priorRegressionsByPair = /* @__PURE__ */ new Map();
88870
89025
  if (haveHistory) {
88871
- const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and71(eq84(insights.type, "regression"), inArray33(insights.runId, recentRunIds))).all();
89026
+ const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and71(eq84(insights.type, "regression"), inArray34(insights.runId, recentRunIds))).all();
88872
89027
  const regressionGroups = /* @__PURE__ */ new Map();
88873
89028
  for (const row of priorRows) {
88874
89029
  if (!row.runId) continue;