@canonry/canonry 7.5.1 → 7.7.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 (31) hide show
  1. package/assets/agent-workspace/skills/aero/SKILL.md +39 -1
  2. package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +2 -2
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +8 -0
  4. package/assets/assets/{AuditHistoryPanel-B5aLMnWE.js → AuditHistoryPanel-qumC-I56.js} +1 -1
  5. package/assets/assets/{BacklinksPage-Biq1jrqe.js → BacklinksPage-BNyYcY5w.js} +1 -1
  6. package/assets/assets/{HistoryPage-CGGkAgnz.js → HistoryPage-CQfOM6NA.js} +1 -1
  7. package/assets/assets/{MeasurementPropertyPage-BwyWGGBg.js → MeasurementPropertyPage-D0LTQHL7.js} +1 -1
  8. package/assets/assets/{ProjectPage-DEnKyD3e.js → ProjectPage-QQErJAT8.js} +1 -1
  9. package/assets/assets/{RunsPage-DNBn0Rau.js → RunsPage-CniAGDVF.js} +1 -1
  10. package/assets/assets/{SettingsPage-D3m-BLuf.js → SettingsPage-BPsrE4ao.js} +1 -1
  11. package/assets/assets/{SiteHealthSection-CPMu1l-l.js → SiteHealthSection-zW3ykBCu.js} +3 -3
  12. package/assets/assets/{TrafficPage-BCK_V__i.js → TrafficPage-DXKk92zy.js} +1 -1
  13. package/assets/assets/{TrafficSourceDetailPage-DaCehUm8.js → TrafficSourceDetailPage-4POLIA_c.js} +1 -1
  14. package/assets/assets/{extract-error-message-CqBLzzuR.js → extract-error-message-C6t0hB2w.js} +1 -1
  15. package/assets/assets/{index-C2X_UARl.js → index-DBQ-8jB1.js} +24 -24
  16. package/assets/assets/{react-sigma_core.esm.min-BvO4SZKT.js → react-sigma_core.esm.min-D7GjzWYV.js} +1 -1
  17. package/assets/assets/{v2-overview-adapter-CgDChBa5.js → v2-overview-adapter-ChE5k_dV.js} +1 -1
  18. package/assets/index.html +1 -1
  19. package/dist/{chunk-VVEMJCC6.js → chunk-3DB43KT2.js} +4 -2
  20. package/dist/{chunk-JTQ4KFIR.js → chunk-75RSUOHZ.js} +430 -279
  21. package/dist/{chunk-Y7K5NMNV.js → chunk-JJXTHJ4E.js} +2 -2
  22. package/dist/{chunk-HAWCV4SU.js → chunk-LFUSODDL.js} +45 -22
  23. package/dist/{chunk-KJIXDPYH.js → chunk-ODEAE5T5.js} +3 -3
  24. package/dist/{chunk-56YOI7QX.js → chunk-WBTYXLXL.js} +2 -2
  25. package/dist/{chunk-RVM6QJQT.js → chunk-WJJTKZKK.js} +5509 -5464
  26. package/dist/cli.js +24 -12
  27. package/dist/{demo-server-V3DDLXND.js → demo-server-UWBPY743.js} +4 -4
  28. package/dist/index.js +6 -6
  29. package/dist/{intelligence-service-MZVPWIXL.js → intelligence-service-LOH37GPJ.js} +2 -2
  30. package/dist/mcp.js +4 -4
  31. package/package.json +8 -8
@@ -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-RVM6QJQT.js";
803
+ } from "./chunk-WJJTKZKK.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 = [
@@ -14069,8 +14085,9 @@ function outcome(status, result) {
14069
14085
  }
14070
14086
  function parse(schema, value) {
14071
14087
  const result = schema.safeParse(value);
14072
- if (!result.success) throw validationError("Invalid sentiment request.", { issues: result.error.issues });
14073
- return result.data;
14088
+ if (result.success) return result.data;
14089
+ const first = Array.isArray(result.error.issues) ? result.error.issues[0]?.message : void 0;
14090
+ throw validationError(typeof first === "string" ? `Invalid sentiment request: ${first}` : "Invalid sentiment request.", { issues: result.error.issues });
14074
14091
  }
14075
14092
 
14076
14093
  // ../api-routes/src/sentiment.ts
@@ -15288,7 +15305,7 @@ function pruneProviderDispatchModes(modes, providers, revisionProviders) {
15288
15305
 
15289
15306
  // ../api-routes/src/run-queue.ts
15290
15307
  import crypto10 from "crypto";
15291
- import { and as and10, eq as eq16, or as or4 } from "drizzle-orm";
15308
+ import { and as and10, desc as desc7, eq as eq16, gt as gt3, inArray as inArray6, or as or4 } from "drizzle-orm";
15292
15309
 
15293
15310
  // ../api-routes/src/measurement-report-adapter.ts
15294
15311
  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 +16924,92 @@ function resolveQueueDispatch(tx, params, stamp) {
16907
16924
  }
16908
16925
  return resolution;
16909
16926
  }
16927
+ function providersARunWouldCall(roster, runnable) {
16928
+ const listed = normalizeProviders(roster);
16929
+ if (runnable == null) return listed;
16930
+ const available = new Set(normalizeProviders(runnable));
16931
+ return listed.filter((provider) => available.has(provider));
16932
+ }
16933
+ var PROVIDER_ACCOUNT_LOOKBACK = PROVIDER_ACCOUNT_FAILURE_STREAK * 5;
16934
+ function providerSettingsChangeCouldFix(action, diff) {
16935
+ if (action === "provider.created") return true;
16936
+ try {
16937
+ const parsed = JSON.parse(diff ?? "null");
16938
+ if (!parsed) return false;
16939
+ if (parsed.apiKeyRotated) return true;
16940
+ const before = parsed.before ?? {};
16941
+ const after = parsed.after ?? {};
16942
+ return before.configured !== after.configured || before.model !== after.model || before.baseUrl !== after.baseUrl;
16943
+ } catch {
16944
+ return false;
16945
+ }
16946
+ }
16947
+ function providerAccountRefusal(db, params) {
16948
+ if (params.force || params.trigger === RunTriggers.probe) return null;
16949
+ const recent = db.select({
16950
+ id: runs.id,
16951
+ status: runs.status,
16952
+ error: runs.error,
16953
+ createdAt: runs.createdAt,
16954
+ finishedAt: runs.finishedAt
16955
+ }).from(runs).where(and10(
16956
+ eq16(runs.projectId, params.projectId),
16957
+ eq16(runs.kind, RunKinds["answer-visibility"]),
16958
+ inArray6(runs.status, [RunStatuses.completed, RunStatuses.partial, RunStatuses.failed, RunStatuses.cancelled])
16959
+ )).orderBy(desc7(runs.createdAt), desc7(runs.id)).limit(PROVIDER_ACCOUNT_LOOKBACK).all().map((run) => ({ ...run, providers: parseRunError(run.error)?.providers ?? {} }));
16960
+ const withAccountFailure = recent.filter((run) => Object.values(run.providers).some((entry) => isProviderAccountFailure(entry.code)));
16961
+ if (withAccountFailure.length < PROVIDER_ACCOUNT_FAILURE_STREAK) return null;
16962
+ const calling = normalizeProviders(params.providers());
16963
+ if (calling.length === 0) return null;
16964
+ 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;
16965
+ const streaks = /* @__PURE__ */ new Map();
16966
+ for (const provider of calling) {
16967
+ let count4 = 0;
16968
+ let newest2 = null;
16969
+ let oldest = null;
16970
+ let code = null;
16971
+ for (const run of recent) {
16972
+ const entry = run.providers[provider];
16973
+ if (!entry) {
16974
+ if (run.status !== RunStatuses.failed && answered2(run.id, provider)) return null;
16975
+ continue;
16976
+ }
16977
+ if (!isProviderAccountFailure(entry.code)) return null;
16978
+ newest2 ??= run;
16979
+ code ??= entry.code;
16980
+ oldest = run;
16981
+ count4 += 1;
16982
+ if (count4 === PROVIDER_ACCOUNT_FAILURE_STREAK) break;
16983
+ }
16984
+ if (count4 < PROVIDER_ACCOUNT_FAILURE_STREAK) return null;
16985
+ streaks.set(provider, { newest: newest2, oldest, code });
16986
+ }
16987
+ const finished = (run) => Date.parse(run.finishedAt ?? run.createdAt);
16988
+ const newest = [...streaks.values()].map((streak) => streak.newest).sort((a, b) => finished(b) - finished(a))[0];
16989
+ const retryAfterMs = finished(newest) + PROVIDER_ACCOUNT_RETRY_HOURS * 36e5;
16990
+ if (Date.parse(params.now) >= retryAfterMs) return null;
16991
+ const since = [...streaks.values()].map((streak) => streak.oldest.createdAt).sort()[0];
16992
+ 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();
16993
+ const fixedSince = settingsChanges.some((change) => {
16994
+ const streak = streaks.get(change.entityId ?? "");
16995
+ return streak !== void 0 && change.createdAt > streak.oldest.createdAt && providerSettingsChangeCouldFix(change.action, change.diff);
16996
+ });
16997
+ if (fixedSince) return null;
16998
+ return {
16999
+ consecutiveRuns: PROVIDER_ACCOUNT_FAILURE_STREAK,
17000
+ latestRunId: newest.id,
17001
+ since,
17002
+ retryAfter: new Date(retryAfterMs).toISOString(),
17003
+ providers: Object.fromEntries(calling.map((provider) => [provider, streaks.get(provider).code]))
17004
+ };
17005
+ }
17006
+ function providersFailingError(projectName, failures) {
17007
+ const named = Object.entries(failures.providers).map(([provider, code]) => `${provider} (${code})`).join(", ");
17008
+ return providersFailing(
17009
+ `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.`,
17010
+ { projectName, ...failures }
17011
+ );
17012
+ }
16910
17013
  function queueRunIfProjectIdle(db, params) {
16911
17014
  const createdAt = params.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
16912
17015
  const kind = params.kind ?? "answer-visibility";
@@ -16947,6 +17050,17 @@ function queueRunIfProjectIdle(db, params) {
16947
17050
  }
16948
17051
  const current = activeRun();
16949
17052
  if (current) return { conflict: true, activeRunId: current.id };
17053
+ const refused = kind === RunKinds["answer-visibility"] ? providerAccountRefusal(tx, {
17054
+ projectId: params.projectId,
17055
+ trigger: stamp?.scope ? RunTriggers.probe : trigger,
17056
+ force: params.force ?? false,
17057
+ now: createdAt,
17058
+ providers: () => providersARunWouldCall(
17059
+ stamp?.identity.providers ?? providerRoster(tx, params),
17060
+ params.runnableProviders
17061
+ )
17062
+ }) : null;
17063
+ if (refused) return { conflict: false, refused };
16950
17064
  const scoped = params.queries != null || stamp?.scope != null;
16951
17065
  const basket = scoped ? null : ensureCurrentQueryBasketRevision(tx, params.projectId, createdAt);
16952
17066
  tx.insert(runs).values({
@@ -16978,7 +17092,7 @@ function queueRunIfProjectIdle(db, params) {
16978
17092
  }
16979
17093
 
16980
17094
  // ../api-routes/src/provider-batches.ts
16981
- import { and as and11, asc as asc2, eq as eq17, inArray as inArray6 } from "drizzle-orm";
17095
+ import { and as and11, asc as asc2, eq as eq17, inArray as inArray7 } from "drizzle-orm";
16982
17096
  function formatProviderBatchSummary(row) {
16983
17097
  return {
16984
17098
  id: row.id,
@@ -17001,10 +17115,10 @@ function runHadProviderBatch(db, runId) {
17001
17115
  return db.select({ id: providerBatches.id }).from(providerBatches).where(eq17(providerBatches.runId, runId)).limit(1).get() !== void 0;
17002
17116
  }
17003
17117
  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;
17118
+ 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
17119
  }
17006
17120
  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);
17121
+ 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
17122
  }
17009
17123
 
17010
17124
  // ../api-routes/src/projects.ts
@@ -17571,13 +17685,13 @@ function aliasArraysEqual(a, b) {
17571
17685
 
17572
17686
  // ../api-routes/src/queries.ts
17573
17687
  import crypto13 from "crypto";
17574
- import { and as and14, eq as eq20, inArray as inArray8, sql as sql8 } from "drizzle-orm";
17688
+ import { and as and14, eq as eq20, inArray as inArray9, sql as sql8 } from "drizzle-orm";
17575
17689
 
17576
17690
  // ../api-routes/src/query-replace.ts
17577
17691
  import crypto12 from "crypto";
17578
- import { and as and13, eq as eq19, inArray as inArray7, isNull as isNull5 } from "drizzle-orm";
17692
+ import { and as and13, eq as eq19, inArray as inArray8, isNull as isNull5 } from "drizzle-orm";
17579
17693
  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();
17694
+ 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
17695
  for (const q of candidates) {
17582
17696
  tx.update(querySnapshots).set({ queryText: q.text }).where(and13(eq19(querySnapshots.queryId, q.id), isNull5(querySnapshots.queryText))).run();
17583
17697
  }
@@ -17640,7 +17754,7 @@ function assertNoActivePlanlessSweep(tx, scope) {
17640
17754
  const activeRun = tx.select({ id: runs.id }).from(runs).where(and13(
17641
17755
  eq19(runs.projectId, scope.projectId),
17642
17756
  eq19(runs.kind, RunKinds["answer-visibility"]),
17643
- inArray7(runs.status, [RunStatuses.queued, RunStatuses.running]),
17757
+ inArray8(runs.status, [RunStatuses.queued, RunStatuses.running]),
17644
17758
  isNull5(runs.measurementPlanVersionId)
17645
17759
  )).get();
17646
17760
  if (activeRun) throw runInProgress(scope.projectName, RunKinds["answer-visibility"], activeRun.id);
@@ -17693,11 +17807,11 @@ function replaceProjectQueries(tx, projectId, incomingTexts, now) {
17693
17807
  for (const dup of diff.duplicates) {
17694
17808
  tx.update(querySnapshots).set({ queryId: dup.keptId }).where(eq19(querySnapshots.queryId, dup.id)).run();
17695
17809
  }
17696
- tx.delete(queries).where(inArray7(queries.id, diff.duplicates.map((d) => d.id))).run();
17810
+ tx.delete(queries).where(inArray8(queries.id, diff.duplicates.map((d) => d.id))).run();
17697
17811
  }
17698
17812
  if (diff.removed.length > 0) {
17699
17813
  const removedIds = diff.removed.map((r) => r.id);
17700
- tx.delete(queries).where(inArray7(queries.id, removedIds)).run();
17814
+ tx.delete(queries).where(inArray8(queries.id, removedIds)).run();
17701
17815
  }
17702
17816
  for (const keptRow of diff.kept) {
17703
17817
  if (keptRow.currentText !== keptRow.incomingText) {
@@ -17792,9 +17906,9 @@ async function queryRoutes(app, opts) {
17792
17906
  let snapshotsDetached = 0;
17793
17907
  let affectedQueries = 0;
17794
17908
  if (removedIds.length > 0) {
17795
- const snapshotCount = app.db.select({ n: sql8`count(*)` }).from(querySnapshots).where(inArray8(querySnapshots.queryId, removedIds)).get();
17909
+ const snapshotCount = app.db.select({ n: sql8`count(*)` }).from(querySnapshots).where(inArray9(querySnapshots.queryId, removedIds)).get();
17796
17910
  snapshotsDetached = snapshotCount?.n ?? 0;
17797
- const distinctAffected = app.db.select({ n: sql8`count(distinct ${querySnapshots.queryId})` }).from(querySnapshots).where(inArray8(querySnapshots.queryId, removedIds)).get();
17911
+ const distinctAffected = app.db.select({ n: sql8`count(distinct ${querySnapshots.queryId})` }).from(querySnapshots).where(inArray9(querySnapshots.queryId, removedIds)).get();
17798
17912
  affectedQueries = distinctAffected?.n ?? 0;
17799
17913
  }
17800
17914
  return reply.send({
@@ -18244,7 +18358,7 @@ function parseBody(schema, value, message) {
18244
18358
  }
18245
18359
 
18246
18360
  // ../api-routes/src/competitor-landscape.ts
18247
- import { and as and17, desc as desc7, eq as eq24, gte as gte3, inArray as inArray9, isNull as isNull6 } from "drizzle-orm";
18361
+ import { and as and17, desc as desc8, eq as eq24, gte as gte3, inArray as inArray10, isNull as isNull6 } from "drizzle-orm";
18248
18362
 
18249
18363
  // ../api-routes/src/mention-share-inputs.ts
18250
18364
  import { eq as eq22 } from "drizzle-orm";
@@ -19057,11 +19171,11 @@ function latestSweepRuns(db, projectId) {
19057
19171
  const candidates = db.select().from(runs).where(and17(
19058
19172
  eq24(runs.projectId, projectId),
19059
19173
  eq24(runs.kind, RunKinds["answer-visibility"]),
19060
- inArray9(runs.status, [RunStatuses.completed, RunStatuses.partial]),
19174
+ inArray10(runs.status, [RunStatuses.completed, RunStatuses.partial]),
19061
19175
  notProbeRun(),
19062
19176
  // A scoped spot check is never the latest sweep.
19063
19177
  isNull6(runs.measurementScope)
19064
- )).orderBy(desc7(runs.createdAt), desc7(runs.id)).all();
19178
+ )).orderBy(desc8(runs.createdAt), desc8(runs.id)).all();
19065
19179
  for (const group of groupRunsByCreatedAt(candidates)) {
19066
19180
  const whole = group.filter((run) => measurementRunCompleteness(db, run.id).complete);
19067
19181
  if (whole.length > 0) return whole;
@@ -19086,8 +19200,8 @@ function readCompetitorLandscape(app, projectName, query, selection) {
19086
19200
  const candidateRuns = app.db.select().from(runs).where(and17(
19087
19201
  eq24(runs.projectId, project.id),
19088
19202
  eq24(runs.kind, RunKinds["answer-visibility"]),
19089
- selection ? inArray9(runs.id, [...selection.runIds]) : void 0,
19090
- latestRunIds ? inArray9(runs.id, latestRunIds) : filters.runId ? eq24(runs.id, filters.runId) : void 0,
19203
+ selection ? inArray10(runs.id, [...selection.runIds]) : void 0,
19204
+ latestRunIds ? inArray10(runs.id, latestRunIds) : filters.runId ? eq24(runs.id, filters.runId) : void 0,
19091
19205
  cutoff ? gte3(runs.createdAt, cutoff) : void 0
19092
19206
  )).all();
19093
19207
  const advanced = filters.groupKey || filters.scope === "all-markets" ? resolveAdvancedScope(app, project.id, filters.groupKey ? "group" : "all-markets", filters.groupKey, candidateRuns) : null;
@@ -19115,7 +19229,7 @@ function readCompetitorLandscape(app, projectName, query, selection) {
19115
19229
  location: querySnapshots.location,
19116
19230
  measurementExecutionId: querySnapshots.measurementExecutionId,
19117
19231
  createdAt: querySnapshots.createdAt
19118
- }).from(querySnapshots).where(inArray9(querySnapshots.runId, candidateRuns.map((run) => run.id))).all();
19232
+ }).from(querySnapshots).where(inArray10(querySnapshots.runId, candidateRuns.map((run) => run.id))).all();
19119
19233
  const runById = new Map(candidateRuns.map((run) => [run.id, run]));
19120
19234
  const selectedIds = selection?.snapshotIds ? new Set(selection.snapshotIds) : null;
19121
19235
  const inScope = allSnapshots.filter((snapshot) => (!selectedIds || selectedIds.has(snapshot.id)) && snapshotMatchesFilters({
@@ -19299,7 +19413,7 @@ function frozenRunScopes(db, projectId, kind, groupKey, candidateRuns) {
19299
19413
  const planVersionIds = [...new Set(candidateRuns.map((run) => run.measurementPlanVersionId).filter((id) => typeof id === "string" && id.length > 0))];
19300
19414
  const historicalVersions = planVersionIds.length === 0 ? [] : db.select().from(measurementPlanVersions).where(and17(
19301
19415
  eq24(measurementPlanVersions.projectId, projectId),
19302
- inArray9(measurementPlanVersions.id, planVersionIds)
19416
+ inArray10(measurementPlanVersions.id, planVersionIds)
19303
19417
  )).all();
19304
19418
  const frozenByVersionId = new Map(historicalVersions.map((version) => [
19305
19419
  version.id,
@@ -19437,12 +19551,12 @@ function mergePins(...collections) {
19437
19551
 
19438
19552
  // ../api-routes/src/runs.ts
19439
19553
  import crypto15 from "crypto";
19440
- 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";
19554
+ 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";
19441
19555
  import { gte as gte4 } from "drizzle-orm";
19442
19556
 
19443
19557
  // ../api-routes/src/run-fill.ts
19444
19558
  import crypto14 from "crypto";
19445
- 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";
19559
+ 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";
19446
19560
  var ACTIVE_STATUSES = ["queued", "running"];
19447
19561
  function normalizeProvider(value) {
19448
19562
  return value.trim().toLocaleLowerCase("en");
@@ -19470,12 +19584,12 @@ function newerFullSweep(db, run) {
19470
19584
  ne5(runs.trigger, RunTriggers.probe),
19471
19585
  isNull7(runs.measurementScope),
19472
19586
  isNull7(runs.queries),
19473
- gt3(runs.createdAt, run.createdAt),
19587
+ gt4(runs.createdAt, run.createdAt),
19474
19588
  or5(
19475
- inArray10(runs.status, ["queued", "running", "completed", "partial"]),
19589
+ inArray11(runs.status, ["queued", "running", "completed", "partial"]),
19476
19590
  sql9`EXISTS (SELECT 1 FROM ${querySnapshots} WHERE ${querySnapshots.runId} = ${runs.id})`
19477
19591
  )
19478
- )).orderBy(desc8(runs.createdAt)).get();
19592
+ )).orderBy(desc9(runs.createdAt)).get();
19479
19593
  }
19480
19594
  function measuredOnRetiredModel(run, provider, missing) {
19481
19595
  const recorded = run.measurementExecutionIdentity?.models[provider];
@@ -19611,16 +19725,16 @@ function evaluateRunFill(db, run, input = {}) {
19611
19725
  return { kind: "fillable", slots, providers, missing };
19612
19726
  }
19613
19727
  function latestFillFor(db, runId) {
19614
- return db.select().from(runFills).where(eq25(runFills.runId, runId)).orderBy(desc8(runFills.createdAt), desc8(runFills.id)).get();
19728
+ return db.select().from(runFills).where(eq25(runFills.runId, runId)).orderBy(desc9(runFills.createdAt), desc9(runFills.id)).get();
19615
19729
  }
19616
19730
  function activeFillFor(db, projectId) {
19617
- return db.select().from(runFills).where(and18(eq25(runFills.projectId, projectId), inArray10(runFills.status, [...ACTIVE_STATUSES]))).get();
19731
+ return db.select().from(runFills).where(and18(eq25(runFills.projectId, projectId), inArray11(runFills.status, [...ACTIVE_STATUSES]))).get();
19618
19732
  }
19619
19733
  function activeSweepFor(db, projectId) {
19620
19734
  return db.select({ id: runs.id }).from(runs).where(and18(
19621
19735
  eq25(runs.projectId, projectId),
19622
19736
  eq25(runs.kind, RunKinds["answer-visibility"]),
19623
- inArray10(runs.status, [...ACTIVE_STATUSES])
19737
+ inArray11(runs.status, [...ACTIVE_STATUSES])
19624
19738
  )).get();
19625
19739
  }
19626
19740
  function readRunCompleteness(db, run, input = {}) {
@@ -19793,6 +19907,22 @@ async function runRoutes(app, opts) {
19793
19907
  if (activeRun) {
19794
19908
  return { conflict: true, activeRunId: activeRun.id };
19795
19909
  }
19910
+ const refused = providerAccountRefusal(tx, {
19911
+ projectId: project.id,
19912
+ trigger,
19913
+ force: body.force ?? false,
19914
+ now,
19915
+ providers: () => {
19916
+ const runnable = opts.getRunnableProviderNames?.();
19917
+ const roster = resolveRunnableProviderSelection({
19918
+ requestedProviders: providers,
19919
+ projectProviders: project.providers,
19920
+ runnableProviders: runnable
19921
+ }).selectedProviders;
19922
+ return providersARunWouldCall(roster, runnable);
19923
+ }
19924
+ });
19925
+ if (refused) return { conflict: false, refused };
19796
19926
  const inserted = [];
19797
19927
  for (const loc of projectLocations) {
19798
19928
  const runId2 = crypto15.randomUUID();
@@ -19813,6 +19943,7 @@ async function runRoutes(app, opts) {
19813
19943
  if (result.conflict) {
19814
19944
  throw runInProgress(project.name, kind, result.activeRunId);
19815
19945
  }
19946
+ if (result.refused) throw providersFailingError(project.name, result.refused);
19816
19947
  const results = [];
19817
19948
  for (const { runId: runId2, loc } of result.inserted) {
19818
19949
  writeAuditLog(app.db, {
@@ -19843,9 +19974,11 @@ async function runRoutes(app, opts) {
19843
19974
  providerModels: opts.getEffectiveProviderModels?.(),
19844
19975
  measurementScope: body.measurementScope ?? null,
19845
19976
  dispatchMode: body.dispatchMode ?? null,
19846
- batchEligibleProviders: opts.getBatchEligibleProviderNames?.() ?? null
19977
+ batchEligibleProviders: opts.getBatchEligibleProviderNames?.() ?? null,
19978
+ force: body.force ?? false
19847
19979
  });
19848
19980
  if (queueResult.conflict) throw runInProgress(project.name, kind, queueResult.activeRunId);
19981
+ if (queueResult.refused) throw providersFailingError(project.name, queueResult.refused);
19849
19982
  const runId = queueResult.runId;
19850
19983
  writeAuditLog(app.db, {
19851
19984
  projectId: project.id,
@@ -19869,14 +20002,14 @@ async function runRoutes(app, opts) {
19869
20002
  if (kind) filters.push(eq26(runs.kind, kind));
19870
20003
  if (status) filters.push(eq26(runs.status, status));
19871
20004
  const where = and19(...filters);
19872
- 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();
20005
+ 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();
19873
20006
  return reply.send(rows.map(formatRun));
19874
20007
  });
19875
20008
  app.get("/projects/:name/runs/latest", async (request, reply) => {
19876
20009
  const project = resolveProject(app.db, request.params.name);
19877
20010
  const countRow = app.db.select({ count: sql10`count(*)` }).from(runs).where(and19(eq26(runs.projectId, project.id), notProbeRun())).get();
19878
20011
  const totalRuns = countRow?.count ?? 0;
19879
- 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();
20012
+ 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();
19880
20013
  if (!latestRun) {
19881
20014
  return reply.send({ totalRuns: 0, run: null });
19882
20015
  }
@@ -19896,7 +20029,7 @@ async function runRoutes(app, opts) {
19896
20029
  if (status) filters.push(eq26(runs.status, status));
19897
20030
  const scopedProjectId = request.apiKey?.projectId;
19898
20031
  if (scopedProjectId) filters.push(eq26(runs.projectId, scopedProjectId));
19899
- const rows = app.db.select().from(runs).where(and19(...filters)).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(limit).all();
20032
+ const rows = app.db.select().from(runs).where(and19(...filters)).orderBy(desc10(runs.createdAt), desc10(runs.id)).limit(limit).all();
19900
20033
  return reply.send(rows.map(formatRun));
19901
20034
  });
19902
20035
  app.post("/runs", async (request, reply) => {
@@ -19913,6 +20046,8 @@ async function runRoutes(app, opts) {
19913
20046
  }
19914
20047
  const dispatchMode = parsedDispatchMode.data ?? null;
19915
20048
  const batchEligibleProviders = opts.getBatchEligibleProviderNames?.() ?? null;
20049
+ const force = request.body?.force;
20050
+ if (force !== void 0 && typeof force !== "boolean") throw validationError('"force" must be a boolean');
19916
20051
  const rawProviders = request.body?.providers;
19917
20052
  if (rawProviders?.length) {
19918
20053
  const normalized = rawProviders.map((p) => p.trim().toLowerCase()).filter(Boolean);
@@ -20008,12 +20143,18 @@ async function runRoutes(app, opts) {
20008
20143
  runnableProviders: runnableProviderNames,
20009
20144
  providerModels: opts.getEffectiveProviderModels?.(),
20010
20145
  dispatchMode,
20011
- batchEligibleProviders
20146
+ batchEligibleProviders,
20147
+ force: force ?? false
20012
20148
  });
20013
20149
  if (queueResult.conflict) {
20014
20150
  results.push({ projectName: project.name, projectId: project.id, status: "conflict", error: "run_in_progress" });
20015
20151
  continue;
20016
20152
  }
20153
+ if (queueResult.refused) {
20154
+ const refusal = providersFailingError(project.name, queueResult.refused);
20155
+ results.push({ projectName: project.name, projectId: project.id, status: "error", error: refusal.message, errorCode: refusal.code });
20156
+ continue;
20157
+ }
20017
20158
  const runId = queueResult.runId;
20018
20159
  writeAuditLog(app.db, {
20019
20160
  projectId: project.id,
@@ -20037,7 +20178,7 @@ async function runRoutes(app, opts) {
20037
20178
  const terminalStatuses = /* @__PURE__ */ new Set(["completed", "partial", "failed", "cancelled"]);
20038
20179
  if (terminalStatuses.has(run.status)) throw runNotCancellable(run.id, run.status);
20039
20180
  const now = (/* @__PURE__ */ new Date()).toISOString();
20040
- 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();
20181
+ 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();
20041
20182
  if (cancelled.changes === 0) {
20042
20183
  const current = app.db.select().from(runs).where(eq26(runs.id, run.id)).get();
20043
20184
  if (!current) throw notFound("Run", run.id);
@@ -20303,7 +20444,7 @@ function loadRunDetail(app, run) {
20303
20444
 
20304
20445
  // ../api-routes/src/measurement-plan.ts
20305
20446
  import crypto16 from "crypto";
20306
- import { and as and20, desc as desc10, eq as eq27 } from "drizzle-orm";
20447
+ import { and as and20, desc as desc11, eq as eq27 } from "drizzle-orm";
20307
20448
  var MEASUREMENT_PLAN_WRITE_SCOPE = "measurement-plan.write";
20308
20449
  function parseStoredPlanAnyVersion(canonicalJson3) {
20309
20450
  return parseStoredMeasurementPlanAnyVersion(canonicalJson3);
@@ -20660,7 +20801,7 @@ async function measurementPlanRoutes(app, opts) {
20660
20801
  app.get("/projects/:name/measurement-plan/versions", async (request) => {
20661
20802
  const project = resolveProject(app.db, request.params.name);
20662
20803
  const active = activePlanVersion(app, project.id);
20663
- const versions = app.db.select().from(measurementPlanVersions).where(eq27(measurementPlanVersions.projectId, project.id)).orderBy(desc10(measurementPlanVersions.revision)).all();
20804
+ const versions = app.db.select().from(measurementPlanVersions).where(eq27(measurementPlanVersions.projectId, project.id)).orderBy(desc11(measurementPlanVersions.revision)).all();
20664
20805
  return {
20665
20806
  versions: versions.map((version) => versionMetadata(version, active?.version.id ?? null))
20666
20807
  };
@@ -21401,7 +21542,7 @@ async function measurementServiceRoutes(app, opts) {
21401
21542
 
21402
21543
  // ../api-routes/src/measurement-draft.ts
21403
21544
  import crypto19 from "crypto";
21404
- import { and as and21, asc as asc4, desc as desc11, eq as eq28, inArray as inArray12 } from "drizzle-orm";
21545
+ import { and as and21, asc as asc4, desc as desc12, eq as eq28, inArray as inArray13 } from "drizzle-orm";
21405
21546
 
21406
21547
  // ../api-routes/src/measurement-draft-compile.ts
21407
21548
  var MEASUREMENT_DRAFT_MAX_TARGETS = 1e3;
@@ -23553,7 +23694,7 @@ async function measurementDraftRoutes(app, opts = {}) {
23553
23694
  // The comparable chain, not the bare active id: a label-only
23554
23695
  // republish must not flip setup back to awaiting_first_run while
23555
23696
  // the overview keeps serving the prior run.
23556
- inArray12(runs.measurementPlanVersionId, comparableMeasurementVersionIds(app.db, project.id, active.id)),
23697
+ inArray13(runs.measurementPlanVersionId, comparableMeasurementVersionIds(app.db, project.id, active.id)),
23557
23698
  eq28(runs.status, RunStatuses.completed)
23558
23699
  )).get() : void 0;
23559
23700
  const state = activeSchemaVersion === 1 ? "republish_required" : draft ? "setup_in_progress" : active ? completedRun ? "operational" : "awaiting_first_run" : "simple";
@@ -24038,7 +24179,7 @@ async function measurementDraftRoutes(app, opts = {}) {
24038
24179
  }));
24039
24180
  return settle(false, active, parseV2Plan(active));
24040
24181
  }
24041
- const latest = tx.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq28(measurementPlanVersions.projectId, gate.project.id)).orderBy(desc11(measurementPlanVersions.revision)).get();
24182
+ const latest = tx.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq28(measurementPlanVersions.projectId, gate.project.id)).orderBy(desc12(measurementPlanVersions.revision)).get();
24042
24183
  const revision = (latest?.revision ?? 0) + 1;
24043
24184
  const canonicalJson3 = canonicalMeasurementPlanV2Json(compiled.plan);
24044
24185
  const versionId = crypto19.randomUUID();
@@ -24175,7 +24316,7 @@ async function measurementDraftRoutes(app, opts = {}) {
24175
24316
  const sets = app.db.select().from(measurementQuerySets).where(eq28(measurementQuerySets.projectId, project.id)).orderBy(asc4(measurementQuerySets.name)).all();
24176
24317
  const counts2 = /* @__PURE__ */ new Map();
24177
24318
  if (sets.length) {
24178
- for (const item2 of app.db.select({ querySetId: measurementQuerySetItems.querySetId }).from(measurementQuerySetItems).where(inArray12(measurementQuerySetItems.querySetId, sets.map((set) => set.id))).all()) {
24319
+ for (const item2 of app.db.select({ querySetId: measurementQuerySetItems.querySetId }).from(measurementQuerySetItems).where(inArray13(measurementQuerySetItems.querySetId, sets.map((set) => set.id))).all()) {
24179
24320
  counts2.set(item2.querySetId, (counts2.get(item2.querySetId) ?? 0) + 1);
24180
24321
  }
24181
24322
  }
@@ -24404,7 +24545,7 @@ async function measurementDraftRoutes(app, opts = {}) {
24404
24545
  diff: { created: created.length, existing: existing.length }
24405
24546
  }));
24406
24547
  if (!querySet) return;
24407
- const highest = tx.select({ position: measurementQuerySetItems.position }).from(measurementQuerySetItems).where(eq28(measurementQuerySetItems.querySetId, querySet.id)).orderBy(desc11(measurementQuerySetItems.position)).get();
24548
+ const highest = tx.select({ position: measurementQuerySetItems.position }).from(measurementQuerySetItems).where(eq28(measurementQuerySetItems.querySetId, querySet.id)).orderBy(desc12(measurementQuerySetItems.position)).get();
24408
24549
  let position = (highest?.position ?? -1) + 1;
24409
24550
  const present = new Set(tx.select({ queryId: measurementQuerySetItems.queryId }).from(measurementQuerySetItems).where(eq28(measurementQuerySetItems.querySetId, querySet.id)).all().map((item2) => item2.queryId));
24410
24551
  for (const entry of ordered) {
@@ -25077,10 +25218,10 @@ async function measurementPropertyEvidenceRoutes(app) {
25077
25218
  }
25078
25219
 
25079
25220
  // ../api-routes/src/measurement-portfolio-reads.ts
25080
- import { and as and25, desc as desc12, eq as eq32, inArray as inArray14, lt as lt5, or as or7 } from "drizzle-orm";
25221
+ import { and as and25, desc as desc13, eq as eq32, inArray as inArray15, lt as lt5, or as or7 } from "drizzle-orm";
25081
25222
 
25082
25223
  // ../api-routes/src/measurement-question-reads.ts
25083
- import { and as and24, eq as eq31, getTableColumns, inArray as inArray13, sql as sql11 } from "drizzle-orm";
25224
+ import { and as and24, eq as eq31, getTableColumns, inArray as inArray14, sql as sql11 } from "drizzle-orm";
25084
25225
  var DEFAULT_LIMIT2 = 50;
25085
25226
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
25086
25227
  RunStatuses.completed,
@@ -25196,7 +25337,7 @@ function selectedQuestionSnapshots(db, runId, manifest, scope) {
25196
25337
  if (scope !== void 0) {
25197
25338
  const executionIds = [...new Set(manifest.expectedSlots.map((slot) => slot.executionId))];
25198
25339
  if (executionIds.length === 0) return [];
25199
- conditions.push(inArray13(querySnapshots.measurementExecutionId, executionIds));
25340
+ conditions.push(inArray14(querySnapshots.measurementExecutionId, executionIds));
25200
25341
  }
25201
25342
  if (scope?.provider !== void 0) {
25202
25343
  conditions.push(sql11`lower(trim(${querySnapshots.provider})) = ${normalizeText(scope.provider)}`);
@@ -25211,7 +25352,7 @@ function rawResponsesForLegacyQuestionSnapshots(db, runId, snapshots) {
25211
25352
  rawResponse: querySnapshots.rawResponse
25212
25353
  }).from(querySnapshots).where(and24(
25213
25354
  eq31(querySnapshots.runId, runId),
25214
- inArray13(querySnapshots.id, legacyIds)
25355
+ inArray14(querySnapshots.id, legacyIds)
25215
25356
  )).all().map((snapshot) => [snapshot.id, snapshot.rawResponse]));
25216
25357
  }
25217
25358
  function withLegacyRawEvidence(db, runId, snapshots) {
@@ -26140,14 +26281,14 @@ function previousComparableRun(db, active, current) {
26140
26281
  // republish: a run pinned to a comparable prior revision measured exactly
26141
26282
  // the questions the active revision asks. The execution-identity and scope
26142
26283
  // checks below still gate what actually compares.
26143
- inArray14(runs.measurementPlanVersionId, comparableMeasurementVersionIds(db, current.projectId, active.version.id)),
26284
+ inArray15(runs.measurementPlanVersionId, comparableMeasurementVersionIds(db, current.projectId, active.version.id)),
26144
26285
  eq32(runs.kind, RunKinds["answer-visibility"]),
26145
- inArray14(runs.status, [RunStatuses.completed, RunStatuses.partial]),
26286
+ inArray15(runs.status, [RunStatuses.completed, RunStatuses.partial]),
26146
26287
  or7(
26147
26288
  lt5(runs.createdAt, current.createdAt),
26148
26289
  and25(eq32(runs.createdAt, current.createdAt), lt5(runs.id, current.id))
26149
26290
  )
26150
- )).orderBy(desc12(runs.createdAt), desc12(runs.id)).all().filter((candidate) => (
26291
+ )).orderBy(desc13(runs.createdAt), desc13(runs.id)).all().filter((candidate) => (
26151
26292
  // Full reporting never admits probes. A plan slice is itself stored as a
26152
26293
  // probe, so an explicitly selected slice compares only with other slices;
26153
26294
  // the exact frozen scope check below then keeps the population identical.
@@ -26399,7 +26540,7 @@ function unattributedByClass(plan, run, materialized) {
26399
26540
  return { branded: read("branded"), nonBrand: read("non-brand") };
26400
26541
  }
26401
26542
  function latestRunFill(db, runId) {
26402
- const fill = db.select().from(runFills).where(eq32(runFills.runId, runId)).orderBy(desc12(runFills.createdAt), desc12(runFills.id)).get();
26543
+ const fill = db.select().from(runFills).where(eq32(runFills.runId, runId)).orderBy(desc13(runFills.createdAt), desc13(runFills.id)).get();
26403
26544
  if (!fill) return null;
26404
26545
  const { status, providers, expected, filled, createdAt, finishedAt } = formatRunFill(fill);
26405
26546
  return { status, providers, expected, filled, createdAt, finishedAt };
@@ -26551,7 +26692,7 @@ async function measurementPortfolioReadRoutes(app) {
26551
26692
 
26552
26693
  // ../api-routes/src/visibility-report.ts
26553
26694
  import { createHash as createHash7 } from "crypto";
26554
- 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";
26695
+ 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";
26555
26696
 
26556
26697
  // ../api-routes/src/measurement-scope-options.ts
26557
26698
  function marketLinks(keys, settings) {
@@ -27370,7 +27511,7 @@ function loadVisibilitySnapshots(db, runIds) {
27370
27511
  requestedContext: querySnapshots.requestedContext,
27371
27512
  supportedContext: querySnapshots.supportedContext,
27372
27513
  createdAt: querySnapshots.createdAt
27373
- }).from(querySnapshots).where(inArray15(querySnapshots.runId, [...runIds])).all();
27514
+ }).from(querySnapshots).where(inArray16(querySnapshots.runId, [...runIds])).all();
27374
27515
  for (const row of rows) {
27375
27516
  const snapshots = byRun.get(row.runId) ?? [];
27376
27517
  snapshots.push(row);
@@ -27783,7 +27924,7 @@ function completedVisibilityRuns(db, projectId, planless, query) {
27783
27924
  return db.select().from(runs).where(and26(
27784
27925
  eq33(runs.projectId, projectId),
27785
27926
  eq33(runs.kind, RunKinds["answer-visibility"]),
27786
- inArray15(runs.status, [RunStatuses.completed, RunStatuses.partial]),
27927
+ inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
27787
27928
  notProbeRun(),
27788
27929
  planless ? isNull8(runs.measurementPlanVersionId) : isNotNull4(runs.measurementPlanVersionId),
27789
27930
  // A scoped spot check is never a whole-project sweep. It can be inspected
@@ -27792,13 +27933,13 @@ function completedVisibilityRuns(db, projectId, planless, query) {
27792
27933
  query.runId === void 0 ? void 0 : eq33(runs.id, query.runId),
27793
27934
  query.from === void 0 ? void 0 : gte5(runs.createdAt, query.from),
27794
27935
  query.to === void 0 ? void 0 : lte6(runs.createdAt, query.to)
27795
- )).orderBy(desc13(runs.createdAt), desc13(runs.id)).limit(VISIBILITY_REPORT_MAX_RUNS).all();
27936
+ )).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(VISIBILITY_REPORT_MAX_RUNS).all();
27796
27937
  }
27797
27938
  function previousEligibleVisibilityRun(db, projectId, planless, selected) {
27798
27939
  return db.select().from(runs).where(and26(
27799
27940
  eq33(runs.projectId, projectId),
27800
27941
  eq33(runs.kind, RunKinds["answer-visibility"]),
27801
- inArray15(runs.status, [RunStatuses.completed, RunStatuses.partial]),
27942
+ inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
27802
27943
  notProbeRun(),
27803
27944
  planless ? isNull8(runs.measurementPlanVersionId) : isNotNull4(runs.measurementPlanVersionId),
27804
27945
  isNull8(runs.measurementScope),
@@ -27806,7 +27947,7 @@ function previousEligibleVisibilityRun(db, projectId, planless, selected) {
27806
27947
  lt6(runs.createdAt, selected.createdAt),
27807
27948
  and26(eq33(runs.createdAt, selected.createdAt), lt6(runs.id, selected.id))
27808
27949
  )
27809
- )).orderBy(desc13(runs.createdAt), desc13(runs.id)).limit(1).get();
27950
+ )).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(1).get();
27810
27951
  }
27811
27952
  function readPreviousSweep(read) {
27812
27953
  try {
@@ -27937,7 +28078,7 @@ function frozenSimpleDefinitions(db, projectId, runIds) {
27937
28078
  if (runIds.length === 0) return /* @__PURE__ */ new Map();
27938
28079
  return new Map(db.select().from(simpleMeasurementDefinitions).where(and26(
27939
28080
  eq33(simpleMeasurementDefinitions.projectId, projectId),
27940
- inArray15(simpleMeasurementDefinitions.runId, [...runIds])
28081
+ inArray16(simpleMeasurementDefinitions.runId, [...runIds])
27941
28082
  )).all().map((row) => [row.runId, row.definition]));
27942
28083
  }
27943
28084
  function simpleRunInput(db, project, run, definition, includeEvidence) {
@@ -28006,7 +28147,7 @@ function readVisibilityComparisonRuns(db, projectId, since, until, includeEviden
28006
28147
  const sourceRuns = db.select().from(runs).where(and26(
28007
28148
  eq33(runs.projectId, projectId),
28008
28149
  eq33(runs.kind, RunKinds["answer-visibility"]),
28009
- inArray15(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28150
+ inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28010
28151
  notProbeRun(),
28011
28152
  isNotNull4(runs.measurementPlanVersionId),
28012
28153
  isNull8(runs.measurementScope),
@@ -28036,7 +28177,7 @@ function readVisibilityComparisonRuns(db, projectId, since, until, includeEviden
28036
28177
 
28037
28178
  // ../api-routes/src/query-tracking.ts
28038
28179
  import crypto21 from "crypto";
28039
- 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";
28180
+ 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";
28040
28181
  var SOURCE_LIMIT = 100;
28041
28182
  var MAX_REVIEW_AGE_MS = 15 * 60 * 1e3;
28042
28183
  var MAX_REVIEW_FUTURE_SKEW_MS = 60 * 1e3;
@@ -28222,11 +28363,11 @@ function simpleMeasuredAtByQuery(db, project, queryRows2, opts) {
28222
28363
  }).from(runs).where(and27(
28223
28364
  eq34(runs.projectId, project.id),
28224
28365
  eq34(runs.kind, RunKinds["answer-visibility"]),
28225
- inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28366
+ inArray17(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28226
28367
  ne6(runs.trigger, RunTriggers.probe),
28227
28368
  isNull9(runs.measurementScope),
28228
28369
  isNull9(runs.measurementPlanVersionId)
28229
- )).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(SOURCE_LIMIT).all();
28370
+ )).orderBy(desc15(runs.createdAt), desc15(runs.id)).limit(SOURCE_LIMIT).all();
28230
28371
  if (eligibleRuns.length === 0) return /* @__PURE__ */ new Map();
28231
28372
  const frozenByRun = /* @__PURE__ */ new Map();
28232
28373
  for (const row of db.select({
@@ -28234,7 +28375,7 @@ function simpleMeasuredAtByQuery(db, project, queryRows2, opts) {
28234
28375
  definition: simpleMeasurementDefinitions.definition
28235
28376
  }).from(simpleMeasurementDefinitions).where(and27(
28236
28377
  eq34(simpleMeasurementDefinitions.projectId, project.id),
28237
- inArray16(simpleMeasurementDefinitions.runId, eligibleRuns.map((run) => run.id))
28378
+ inArray17(simpleMeasurementDefinitions.runId, eligibleRuns.map((run) => run.id))
28238
28379
  )).all()) {
28239
28380
  const parsed = simpleMeasurementDefinitionSchema.safeParse(row.definition);
28240
28381
  if (parsed.success) frozenByRun.set(row.runId, parsed.data);
@@ -28246,7 +28387,7 @@ function simpleMeasuredAtByQuery(db, project, queryRows2, opts) {
28246
28387
  queryId: querySnapshots.queryId,
28247
28388
  queryText: querySnapshots.queryText,
28248
28389
  provider: querySnapshots.provider
28249
- }).from(querySnapshots).where(inArray16(querySnapshots.runId, [...frozenByRun.keys()])).all()) {
28390
+ }).from(querySnapshots).where(inArray17(querySnapshots.runId, [...frozenByRun.keys()])).all()) {
28250
28391
  if (!snapshot.queryId) continue;
28251
28392
  const byQuery = snapshotsByRunQuery.get(snapshot.runId) ?? /* @__PURE__ */ new Map();
28252
28393
  const rows = byQuery.get(snapshot.queryId) ?? [];
@@ -28344,11 +28485,11 @@ function measuredAtByQuery(db, state, opts) {
28344
28485
  const eligibleRuns = db.select().from(runs).where(and27(
28345
28486
  eq34(runs.projectId, project.id),
28346
28487
  eq34(runs.kind, RunKinds["answer-visibility"]),
28347
- inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28488
+ inArray17(runs.status, [RunStatuses.completed, RunStatuses.partial]),
28348
28489
  ne6(runs.trigger, RunTriggers.probe),
28349
28490
  isNull9(runs.measurementScope),
28350
28491
  isNotNull5(runs.measurementPlanVersionId)
28351
- )).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(SOURCE_LIMIT).all();
28492
+ )).orderBy(desc15(runs.createdAt), desc15(runs.id)).limit(SOURCE_LIMIT).all();
28352
28493
  if (eligibleRuns.length === 0) return /* @__PURE__ */ new Map();
28353
28494
  const versionIds = unique2(eligibleRuns.flatMap((run) => run.measurementPlanVersionId ? [run.measurementPlanVersionId] : []));
28354
28495
  const versionPlans = new Map(db.select({
@@ -28357,7 +28498,7 @@ function measuredAtByQuery(db, state, opts) {
28357
28498
  canonicalJson: measurementPlanVersions.canonicalJson
28358
28499
  }).from(measurementPlanVersions).where(and27(
28359
28500
  eq34(measurementPlanVersions.projectId, project.id),
28360
- inArray16(measurementPlanVersions.id, versionIds)
28501
+ inArray17(measurementPlanVersions.id, versionIds)
28361
28502
  )).all().flatMap((row) => {
28362
28503
  const parsed = parseStoredMeasurementPlanAnyVersion(row.canonicalJson);
28363
28504
  return parsed.schemaVersion === 2 ? [[row.id, { revision: row.revision, plan: parsed }]] : [];
@@ -28389,7 +28530,7 @@ function measuredAtByQuery(db, state, opts) {
28389
28530
  measurementExecutionId: querySnapshots.measurementExecutionId,
28390
28531
  requestedContext: querySnapshots.requestedContext,
28391
28532
  supportedContext: querySnapshots.supportedContext
28392
- }).from(querySnapshots).where(inArray16(querySnapshots.runId, eligibleRuns.map((run) => run.id))).all();
28533
+ }).from(querySnapshots).where(inArray17(querySnapshots.runId, eligibleRuns.map((run) => run.id))).all();
28393
28534
  for (const snapshot of snapshotRows) {
28394
28535
  const snapshots = snapshotsByRun.get(snapshot.runId) ?? [];
28395
28536
  snapshots.push(snapshot);
@@ -28537,13 +28678,13 @@ function savedSources(db, projectId) {
28537
28678
  researchRunQueryId: researchRunQueries.id,
28538
28679
  queryText: researchRunQueries.queryText,
28539
28680
  createdAt: researchRunQueries.createdAt
28540
- }).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);
28681
+ }).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);
28541
28682
  const discovery = db.select({
28542
28683
  discoverySessionId: discoverySessions.id,
28543
28684
  discoveryProbeId: discoveryProbes.id,
28544
28685
  queryText: discoveryProbes.query,
28545
28686
  createdAt: discoveryProbes.createdAt
28546
- }).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);
28687
+ }).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);
28547
28688
  return { research, discovery };
28548
28689
  }
28549
28690
  function workspaceDto(db, state, opts) {
@@ -29398,7 +29539,7 @@ function writeAdvancedCandidate(tx, candidate, request, now) {
29398
29539
  const removed = current.filter((row) => !candidate.queryRows.has(row.id));
29399
29540
  if (removed.length > 0) {
29400
29541
  preserveSnapshotQueryText(tx, candidate.state.project.id, removed.map((row) => row.id));
29401
- tx.delete(queries).where(inArray16(queries.id, removed.map((row) => row.id))).run();
29542
+ tx.delete(queries).where(inArray17(queries.id, removed.map((row) => row.id))).run();
29402
29543
  }
29403
29544
  for (const row of candidate.queryRows.values()) {
29404
29545
  const previous = currentById.get(row.id);
@@ -29417,7 +29558,7 @@ function writeAdvancedCandidate(tx, candidate, request, now) {
29417
29558
  if (!candidate.planChanged) return active;
29418
29559
  const plan = candidate.plan;
29419
29560
  const canonicalJson3 = canonicalMeasurementPlanV2Json(plan);
29420
- const latest = tx.select().from(measurementPlanVersions).where(eq34(measurementPlanVersions.projectId, candidate.state.project.id)).orderBy(desc14(measurementPlanVersions.revision)).get();
29561
+ const latest = tx.select().from(measurementPlanVersions).where(eq34(measurementPlanVersions.projectId, candidate.state.project.id)).orderBy(desc15(measurementPlanVersions.revision)).get();
29421
29562
  const revision = (latest?.revision ?? 0) + 1;
29422
29563
  const versionId = crypto21.randomUUID();
29423
29564
  tx.insert(measurementPlanVersions).values({
@@ -30226,7 +30367,7 @@ function aliasArraysEqual2(a, b) {
30226
30367
  }
30227
30368
 
30228
30369
  // ../api-routes/src/history.ts
30229
- 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";
30370
+ 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";
30230
30371
 
30231
30372
  // ../api-routes/src/notification-redaction.ts
30232
30373
  var REDACTED_URL = {
@@ -30278,27 +30419,27 @@ async function historyRoutes(app) {
30278
30419
  if (!parsed.success) throw validationError("Invalid history cleanup request", { issues: parsed.error.issues });
30279
30420
  const input = parsed.data;
30280
30421
  return app.db.transaction((tx) => {
30281
- 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();
30282
- const activeResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray17(researchRuns.status, ["queued", "running"]))).get();
30422
+ 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();
30423
+ const activeResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray18(researchRuns.status, ["queued", "running"]))).get();
30283
30424
  if (active || activeResearch) throw runInProgress(project.name, active ? "answer-visibility" : "research", (active ?? activeResearch).id);
30284
- 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();
30425
+ 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();
30285
30426
  if (activeFill) throw runFillInProgress(activeFill.runId, activeFill.id);
30286
- 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();
30287
- const selectedResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray17(researchRuns.id, input.researchRunIds))).all();
30427
+ 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();
30428
+ const selectedResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray18(researchRuns.id, input.researchRunIds))).all();
30288
30429
  if (selectedRuns.length !== input.runIds.length || selectedResearch.length !== input.researchRunIds.length) throw notFound("Selected saved run in project", project.name);
30289
30430
  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.");
30290
30431
  const result = {
30291
30432
  dryRun: !input.confirm,
30292
30433
  runIds: input.runIds,
30293
30434
  researchRunIds: input.researchRunIds,
30294
- querySnapshots: tx.select({ value: count() }).from(querySnapshots).where(inArray17(querySnapshots.runId, input.runIds)).get().value,
30295
- researchQueries: tx.select({ value: count() }).from(researchRunQueries).where(inArray17(researchRunQueries.researchRunId, input.researchRunIds)).get().value,
30296
- insights: tx.select({ value: count() }).from(insights).where(inArray17(insights.runId, input.runIds)).get().value,
30297
- healthSnapshots: tx.select({ value: count() }).from(healthSnapshots).where(inArray17(healthSnapshots.runId, input.runIds)).get().value
30435
+ querySnapshots: tx.select({ value: count() }).from(querySnapshots).where(inArray18(querySnapshots.runId, input.runIds)).get().value,
30436
+ researchQueries: tx.select({ value: count() }).from(researchRunQueries).where(inArray18(researchRunQueries.researchRunId, input.researchRunIds)).get().value,
30437
+ insights: tx.select({ value: count() }).from(insights).where(inArray18(insights.runId, input.runIds)).get().value,
30438
+ healthSnapshots: tx.select({ value: count() }).from(healthSnapshots).where(inArray18(healthSnapshots.runId, input.runIds)).get().value
30298
30439
  };
30299
30440
  if (input.confirm) {
30300
- tx.delete(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray17(researchRuns.id, input.researchRunIds))).run();
30301
- tx.delete(runs).where(and29(eq36(runs.projectId, project.id), inArray17(runs.id, input.runIds))).run();
30441
+ tx.delete(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray18(researchRuns.id, input.researchRunIds))).run();
30442
+ tx.delete(runs).where(and29(eq36(runs.projectId, project.id), inArray18(runs.id, input.runIds))).run();
30302
30443
  writeAuditLog(tx, { projectId: project.id, actor: "api", action: "results.cleared", entityType: "project", entityId: project.id, diff: result });
30303
30444
  }
30304
30445
  return result;
@@ -30309,7 +30450,7 @@ async function historyRoutes(app) {
30309
30450
  const filters = [eq36(auditLog.projectId, project.id)];
30310
30451
  if (request.operatorAccess !== true) filters.push(ne7(auditLog.entityType, "telemetry"));
30311
30452
  addAuditHistoryFilters(filters, request.query);
30312
- 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();
30453
+ 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();
30313
30454
  return reply.send(rows.map(formatAuditEntry));
30314
30455
  });
30315
30456
  app.get("/history", async (request, reply) => {
@@ -30317,7 +30458,7 @@ async function historyRoutes(app) {
30317
30458
  const filters = scopedProjectId ? [eq36(auditLog.projectId, scopedProjectId)] : [];
30318
30459
  if (request.operatorAccess !== true) filters.push(ne7(auditLog.entityType, "telemetry"));
30319
30460
  addAuditHistoryFilters(filters, request.query);
30320
- 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();
30461
+ 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();
30321
30462
  return reply.send(rows.map(formatAuditEntry));
30322
30463
  });
30323
30464
  app.get("/projects/:name/snapshots", async (request, reply) => {
@@ -30350,7 +30491,7 @@ async function historyRoutes(app) {
30350
30491
  location: querySnapshots.location,
30351
30492
  rawResponse: querySnapshots.rawResponse,
30352
30493
  createdAt: querySnapshots.createdAt
30353
- }).from(querySnapshots).leftJoin(queries, eq36(querySnapshots.queryId, queries.id)).where(inArray17(querySnapshots.runId, projectRuns.map((r) => r.id))).orderBy(desc15(querySnapshots.createdAt)).all();
30494
+ }).from(querySnapshots).leftJoin(queries, eq36(querySnapshots.queryId, queries.id)).where(inArray18(querySnapshots.runId, projectRuns.map((r) => r.id))).orderBy(desc16(querySnapshots.createdAt)).all();
30354
30495
  const locationFilter = request.query.location;
30355
30496
  const filtered = locationFilter !== void 0 ? allSnapshots.filter((s) => s.location === (locationFilter || null)) : allSnapshots;
30356
30497
  const total = filtered.length;
@@ -30405,12 +30546,12 @@ async function historyRoutes(app) {
30405
30546
  eq36(runs.kind, RunKinds["answer-visibility"])
30406
30547
  );
30407
30548
  const requestedLimit = parseOptionalPositiveInt(request.query.limit, 100);
30408
- 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();
30549
+ 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();
30409
30550
  if (projectRuns.length === 0 || projectQueries.length === 0) {
30410
30551
  return reply.send([]);
30411
30552
  }
30412
30553
  const runIds = new Set(projectRuns.map((r) => r.id));
30413
- const rawSnapshots = app.db.select().from(querySnapshots).where(inArray17(querySnapshots.runId, [...runIds])).all();
30554
+ const rawSnapshots = app.db.select().from(querySnapshots).where(inArray18(querySnapshots.runId, [...runIds])).all();
30414
30555
  const timelineLocationFilter = request.query.location;
30415
30556
  const filteredSnapshots = timelineLocationFilter !== void 0 ? rawSnapshots.filter((s) => s.location === (timelineLocationFilter || null)) : rawSnapshots;
30416
30557
  const allSnapshots = filteredSnapshots.map((snapshot) => ({
@@ -30531,7 +30672,7 @@ async function historyRoutes(app) {
30531
30672
  throw validationError("Both run1 and run2 query params are required");
30532
30673
  }
30533
30674
  const requestedRunIds = [.../* @__PURE__ */ new Set([run1, run2])];
30534
- const runRows = app.db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(inArray17(runs.id, requestedRunIds)).all();
30675
+ const runRows = app.db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(inArray18(runs.id, requestedRunIds)).all();
30535
30676
  const runsById = new Map(runRows.map((row) => [row.id, row]));
30536
30677
  for (const runId of requestedRunIds) {
30537
30678
  const run = runsById.get(runId);
@@ -30636,7 +30777,7 @@ function parseOptionalPositiveInt(value, max2) {
30636
30777
  }
30637
30778
 
30638
30779
  // ../api-routes/src/analytics.ts
30639
- import { and as and30, desc as desc16, eq as eq37, gte as gte7, inArray as inArray18, lt as lt7 } from "drizzle-orm";
30780
+ import { and as and30, desc as desc17, eq as eq37, gte as gte7, inArray as inArray19, lt as lt7 } from "drizzle-orm";
30640
30781
 
30641
30782
  // ../api-routes/src/analytics-model-attribution.ts
30642
30783
  function logicalSweeps(observations) {
@@ -30732,10 +30873,10 @@ async function analyticsRoutes(app) {
30732
30873
  const projectRuns = app.db.select().from(runs).where(and30(
30733
30874
  eq37(runs.projectId, project.id),
30734
30875
  eq37(runs.kind, RunKinds["answer-visibility"]),
30735
- inArray18(runs.status, [RunStatuses.completed, RunStatuses.partial]),
30876
+ inArray19(runs.status, [RunStatuses.completed, RunStatuses.partial]),
30736
30877
  notProbeRun(),
30737
30878
  cutoff ? gte7(runs.createdAt, cutoff) : void 0
30738
- )).orderBy(desc16(runs.createdAt)).all().filter((r) => measuredWhole(app.db, r)).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
30879
+ )).orderBy(desc17(runs.createdAt)).all().filter((r) => measuredWhole(app.db, r)).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
30739
30880
  if (projectRuns.length === 0) {
30740
30881
  return reply.send({
30741
30882
  window,
@@ -30777,7 +30918,7 @@ async function analyticsRoutes(app) {
30777
30918
  citationState: querySnapshots.citationState,
30778
30919
  answerMentioned: querySnapshots.answerMentioned,
30779
30920
  answerText: querySnapshots.answerText
30780
- }).from(querySnapshots).where(inArray18(querySnapshots.runId, runIds)).all();
30921
+ }).from(querySnapshots).where(inArray19(querySnapshots.runId, runIds)).all();
30781
30922
  const rawSnapshots = referenceBasket ? loadedSnapshots.filter(
30782
30923
  (s) => s.queryId !== null || s.queryText !== null && referenceBasket.has(normalizeQueryText(s.queryText))
30783
30924
  ) : filterTrackedSnapshots(loadedSnapshots);
@@ -30827,11 +30968,11 @@ async function analyticsRoutes(app) {
30827
30968
  const anchorRunPredicate = and30(
30828
30969
  eq37(runs.projectId, project.id),
30829
30970
  eq37(runs.kind, RunKinds["answer-visibility"]),
30830
- inArray18(runs.status, [RunStatuses.completed, RunStatuses.partial]),
30971
+ inArray19(runs.status, [RunStatuses.completed, RunStatuses.partial]),
30831
30972
  notProbeRun(),
30832
30973
  lt7(runs.createdAt, cutoff)
30833
30974
  );
30834
- 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);
30975
+ 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);
30835
30976
  const anchorScanTruncated = anchorSweepTimes.length > ANCHOR_SWEEP_SCAN_LIMIT;
30836
30977
  if (anchorScanTruncated) anchorSweepTimes.length = ANCHOR_SWEEP_SCAN_LIMIT;
30837
30978
  if (anchorSweepTimes.length > 0) {
@@ -30857,7 +30998,7 @@ async function analyticsRoutes(app) {
30857
30998
  provider: querySnapshots.provider,
30858
30999
  model: querySnapshots.model,
30859
31000
  servedModel: querySnapshots.servedModel
30860
- }).from(querySnapshots).where(inArray18(querySnapshots.runId, runIds2)).all())) {
31001
+ }).from(querySnapshots).where(inArray19(querySnapshots.runId, runIds2)).all())) {
30861
31002
  if (pending.has(snapshot.provider)) {
30862
31003
  const models = modelsByProvider.get(snapshot.provider) ?? [];
30863
31004
  models.push(snapshot.model);
@@ -30986,7 +31127,7 @@ async function analyticsRoutes(app) {
30986
31127
  const project = resolveProject(app.db, request.params.name);
30987
31128
  const window = parseWindow(request.query.window);
30988
31129
  const cutoff = windowCutoff(window);
30989
- 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));
31130
+ 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));
30990
31131
  const latestGroup = groupRunsByCreatedAt(completedRuns)[0] ?? [];
30991
31132
  const latestGroupRunIds = latestGroup.map((r) => r.id);
30992
31133
  const latestRun = pickGroupRepresentative(latestGroup);
@@ -31009,7 +31150,7 @@ async function analyticsRoutes(app) {
31009
31150
  citationState: querySnapshots.citationState,
31010
31151
  answerMentioned: querySnapshots.answerMentioned,
31011
31152
  answerText: querySnapshots.answerText
31012
- }).from(querySnapshots).where(inArray18(querySnapshots.runId, windowRunIds)).all());
31153
+ }).from(querySnapshots).where(inArray19(querySnapshots.runId, windowRunIds)).all());
31013
31154
  for (const s of allWindowSnaps) {
31014
31155
  const timePoint = runIdToCreatedAt.get(s.runId) ?? s.runId;
31015
31156
  let entry = consistencyMap.get(s.queryId);
@@ -31030,7 +31171,7 @@ async function analyticsRoutes(app) {
31030
31171
  answerMentioned: querySnapshots.answerMentioned,
31031
31172
  answerText: querySnapshots.answerText,
31032
31173
  citedDomains: querySnapshots.citedDomains
31033
- }).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray18(querySnapshots.runId, latestGroupRunIds)).all());
31174
+ }).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray19(querySnapshots.runId, latestGroupRunIds)).all());
31034
31175
  const snapshots = rawSnapshots.map((s) => ({
31035
31176
  ...s,
31036
31177
  resolvedMentioned: resolveSnapshotAnswerMentioned(s, project)
@@ -31197,8 +31338,8 @@ async function analyticsRoutes(app) {
31197
31338
  eq37(runs.projectId, project.id),
31198
31339
  eq37(runs.kind, RunKinds["answer-visibility"]),
31199
31340
  notProbeRun(),
31200
- latestRuns ? inArray18(runs.id, latestRuns.map((run) => run.id)) : requestedRunId ? eq37(runs.id, requestedRunId) : void 0
31201
- )).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);
31341
+ latestRuns ? inArray19(runs.id, latestRuns.map((run) => run.id)) : requestedRunId ? eq37(runs.id, requestedRunId) : void 0
31342
+ )).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);
31202
31343
  if (windowRuns.length === 0) {
31203
31344
  return reply.send({
31204
31345
  ranked: buildRankedList(/* @__PURE__ */ new Map(), limit, 0, 0),
@@ -31230,7 +31371,7 @@ async function analyticsRoutes(app) {
31230
31371
  citedDomains: querySnapshots.citedDomains,
31231
31372
  citedUrls: querySnapshots.citedUrls,
31232
31373
  measurementExecutionId: querySnapshots.measurementExecutionId
31233
- }).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray18(querySnapshots.runId, windowRunIds)).all();
31374
+ }).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray19(querySnapshots.runId, windowRunIds)).all();
31234
31375
  let unclassifiedAnswers = 0;
31235
31376
  let snapshots = loadedSnapshots;
31236
31377
  if (splitByClass) {
@@ -31583,7 +31724,7 @@ function buildCategoryCounts(counts2) {
31583
31724
  }
31584
31725
 
31585
31726
  // ../api-routes/src/intelligence.ts
31586
- import { eq as eq38, desc as desc17, and as and31, inArray as inArray19, like as like3 } from "drizzle-orm";
31727
+ import { eq as eq38, desc as desc18, and as and31, inArray as inArray20, like as like3 } from "drizzle-orm";
31587
31728
  var SEVERITY_RANK = { low: 0, medium: 1, high: 2, critical: 3 };
31588
31729
  function severitiesAtOrAbove(min2) {
31589
31730
  const floor = SEVERITY_RANK[min2];
@@ -31713,7 +31854,7 @@ async function intelligenceRoutes(app) {
31713
31854
  }
31714
31855
  const severityFilter = request.query.severity?.trim();
31715
31856
  if (severityFilter) {
31716
- conditions.push(inArray19(insights.severity, severitiesAtOrAbove(severityFilter)));
31857
+ conditions.push(inArray20(insights.severity, severitiesAtOrAbove(severityFilter)));
31717
31858
  }
31718
31859
  let limit;
31719
31860
  if (request.query.limit !== void 0) {
@@ -31723,7 +31864,7 @@ async function intelligenceRoutes(app) {
31723
31864
  }
31724
31865
  limit = parsed;
31725
31866
  }
31726
- const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] : and31(...conditions)).orderBy(desc17(insights.createdAt)).all();
31867
+ const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] : and31(...conditions)).orderBy(desc18(insights.createdAt)).all();
31727
31868
  const showDismissed = request.query.dismissed === "true";
31728
31869
  let result = rows.filter((r) => showDismissed || !r.dismissed).map(mapInsightRow);
31729
31870
  if (limit !== void 0) result = result.slice(0, limit);
@@ -31751,23 +31892,23 @@ async function intelligenceRoutes(app) {
31751
31892
  const projectVisRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(and31(
31752
31893
  eq38(runs.projectId, project.id),
31753
31894
  eq38(runs.kind, RunKinds["answer-visibility"]),
31754
- inArray19(runs.status, [RunStatuses.completed, RunStatuses.partial]),
31895
+ inArray20(runs.status, [RunStatuses.completed, RunStatuses.partial]),
31755
31896
  // Health-latest is the dashboard headline; probe runs must not
31756
31897
  // displace the most recent real visibility sweep.
31757
31898
  notProbeRun()
31758
- )).orderBy(desc17(runs.createdAt), desc17(runs.id)).all();
31899
+ )).orderBy(desc18(runs.createdAt), desc18(runs.id)).all();
31759
31900
  const latestGroup = groupRunsByCreatedAt(projectVisRuns)[0] ?? [];
31760
31901
  const latestGroupRunIds = latestGroup.map((r) => r.id);
31761
31902
  if (latestGroupRunIds.length > 0) {
31762
31903
  const groupRows = app.db.select().from(healthSnapshots).where(and31(
31763
31904
  eq38(healthSnapshots.projectId, project.id),
31764
- inArray19(healthSnapshots.runId, latestGroupRunIds)
31905
+ inArray20(healthSnapshots.runId, latestGroupRunIds)
31765
31906
  )).all();
31766
31907
  if (groupRows.length > 0) {
31767
31908
  return reply.send(aggregateHealthSnapshots(project.id, groupRows));
31768
31909
  }
31769
31910
  }
31770
- const fallback = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc17(healthSnapshots.createdAt)).limit(1).get();
31911
+ const fallback = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc18(healthSnapshots.createdAt)).limit(1).get();
31771
31912
  if (!fallback) {
31772
31913
  return reply.send(emptyHealthSnapshot(project.id));
31773
31914
  }
@@ -31777,13 +31918,13 @@ async function intelligenceRoutes(app) {
31777
31918
  const project = resolveProject(app.db, request.params.name);
31778
31919
  const parsed = request.query.limit ? parseInt(request.query.limit, 10) : NaN;
31779
31920
  const limit = Number.isNaN(parsed) ? 30 : Math.min(Math.max(parsed, 1), 100);
31780
- const rows = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc17(healthSnapshots.createdAt)).limit(limit).all();
31921
+ const rows = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc18(healthSnapshots.createdAt)).limit(limit).all();
31781
31922
  return reply.send(rows.map(mapHealthRow));
31782
31923
  });
31783
31924
  }
31784
31925
 
31785
31926
  // ../api-routes/src/traffic-analytics.ts
31786
- 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";
31927
+ 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";
31787
31928
 
31788
31929
  // ../api-routes/src/ai-referral-status.ts
31789
31930
  import { and as and32, sql as sql12 } from "drizzle-orm";
@@ -31993,7 +32134,7 @@ function readTrafficActivity(db, projectId, windowDays2) {
31993
32134
  gte8(crawlerEventsHourly.tsHour, headlineStart),
31994
32135
  lte7(crawlerEventsHourly.tsHour, headlineEnd)
31995
32136
  )
31996
- ).groupBy(crawlerEventsHourly.pathNormalized).orderBy(desc18(sql13`SUM(${crawlerEventsHourly.hits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
32137
+ ).groupBy(crawlerEventsHourly.pathNormalized).orderBy(desc19(sql13`SUM(${crawlerEventsHourly.hits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
31997
32138
  const topCrawledPaths = topPathsRows.map((r) => ({
31998
32139
  path: r.path,
31999
32140
  verifiedHits: Number(r.verifiedHits),
@@ -32011,7 +32152,7 @@ function readTrafficActivity(db, projectId, windowDays2) {
32011
32152
  gte8(aiReferralEventsHourly.tsHour, headlineStart),
32012
32153
  lte7(aiReferralEventsHourly.tsHour, headlineEnd)
32013
32154
  )
32014
- ).groupBy(aiReferralEventsHourly.product).orderBy(desc18(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).all();
32155
+ ).groupBy(aiReferralEventsHourly.product).orderBy(desc19(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).all();
32015
32156
  const referralProducts = referralProductsRows.map((r) => ({
32016
32157
  product: r.product,
32017
32158
  arrivals: Number(r.arrivals),
@@ -32028,7 +32169,7 @@ function readTrafficActivity(db, projectId, windowDays2) {
32028
32169
  gte8(aiReferralEventsHourly.tsHour, headlineStart),
32029
32170
  lte7(aiReferralEventsHourly.tsHour, headlineEnd)
32030
32171
  )
32031
- ).groupBy(aiReferralEventsHourly.landingPathNormalized).orderBy(desc18(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
32172
+ ).groupBy(aiReferralEventsHourly.landingPathNormalized).orderBy(desc19(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
32032
32173
  const topReferralLandingPaths = topReferralRows.map((r) => ({
32033
32174
  path: r.path,
32034
32175
  arrivals: Number(r.arrivals),
@@ -32147,7 +32288,7 @@ async function trafficAnalyticsRoutes(app) {
32147
32288
  }
32148
32289
 
32149
32290
  // ../api-routes/src/referral-assessment.ts
32150
- 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";
32291
+ 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";
32151
32292
 
32152
32293
  // ../api-routes/src/ga-ai-referral-aggregation.ts
32153
32294
  function normalizeAiTrafficClass(value) {
@@ -32296,7 +32437,7 @@ function buildAiReferralDailySeries(rows) {
32296
32437
  var DEFAULT_BURST_THRESHOLD = 100;
32297
32438
  var DEFAULT_RATIO_THRESHOLD = 3;
32298
32439
  function latestGaSyncQueriedWindow(db, projectId, startDate, endDate) {
32299
- 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();
32440
+ 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();
32300
32441
  if (!summary3 || startDate < summary3.start || endDate > summary3.end) return false;
32301
32442
  const leftByAnotherSync = db.select({ id: gaAiReferrals.id }).from(gaAiReferrals).where(and34(
32302
32443
  eq40(gaAiReferrals.projectId, projectId),
@@ -32414,7 +32555,7 @@ async function referralAssessmentRoutes(app) {
32414
32555
  }
32415
32556
 
32416
32557
  // ../api-routes/src/organic-evidence.ts
32417
- 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";
32558
+ 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";
32418
32559
 
32419
32560
  // ../api-routes/src/ga-measurement-analysis.ts
32420
32561
  import { and as and35, eq as eq41, gte as gte10, lte as lte9, or as or10, sql as sql15 } from "drizzle-orm";
@@ -33136,7 +33277,7 @@ function buildOrganicEvidence(db, projectName, periodDays) {
33136
33277
  eq42(runs.kind, RunKinds["answer-visibility"]),
33137
33278
  eq42(runs.status, RunStatuses.completed),
33138
33279
  notProbeRun()
33139
- )).orderBy(desc20(runs.createdAt)).get();
33280
+ )).orderBy(desc21(runs.createdAt)).get();
33140
33281
  const snapshots = latest ? db.select().from(querySnapshots).where(eq42(querySnapshots.runId, latest.id)).all() : [];
33141
33282
  const completedAt = latest ? latest.finishedAt ?? latest.createdAt : null;
33142
33283
  const visibility = latest && completedAt ? {
@@ -33376,7 +33517,7 @@ async function organicEvidenceRoutes(app) {
33376
33517
  }
33377
33518
 
33378
33519
  // ../api-routes/src/citations.ts
33379
- import { and as and37, eq as eq43, inArray as inArray20 } from "drizzle-orm";
33520
+ import { and as and37, eq as eq43, inArray as inArray21 } from "drizzle-orm";
33380
33521
  async function citationRoutes(app) {
33381
33522
  app.get("/projects/:name/citations/visibility", async (request, reply) => {
33382
33523
  const project = resolveProject(app.db, request.params.name);
@@ -33400,7 +33541,7 @@ async function citationRoutes(app) {
33400
33541
  competitorOverlap: querySnapshots.competitorOverlap,
33401
33542
  answerMentioned: querySnapshots.answerMentioned,
33402
33543
  createdAt: querySnapshots.createdAt
33403
- }).from(querySnapshots).where(inArray20(querySnapshots.runId, projectRuns.map((r) => r.id))).all();
33544
+ }).from(querySnapshots).where(inArray21(querySnapshots.runId, projectRuns.map((r) => r.id))).all();
33404
33545
  if (rawSnapshots.length === 0) {
33405
33546
  return reply.send(emptyCitationVisibility("no-runs-yet"));
33406
33547
  }
@@ -33537,7 +33678,7 @@ function computeCitationVisibility(input) {
33537
33678
  }
33538
33679
 
33539
33680
  // ../api-routes/src/visibility-stats.ts
33540
- import { and as and38, desc as desc21, eq as eq44, inArray as inArray21 } from "drizzle-orm";
33681
+ import { and as and38, desc as desc22, eq as eq44, inArray as inArray22 } from "drizzle-orm";
33541
33682
 
33542
33683
  // ../api-routes/src/visibility-compare.ts
33543
33684
  var VISIBILITY_COMPARE_MIN_RUNS = 5;
@@ -34007,7 +34148,7 @@ async function visibilityStatsRoutes(app) {
34007
34148
  lastRuns = n;
34008
34149
  }
34009
34150
  const projectQueries = app.db.select({ id: queries.id, query: queries.query }).from(queries).where(eq44(queries.projectId, project.id)).all();
34010
- 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);
34151
+ 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);
34011
34152
  if (sinceMs !== null) projectRuns = projectRuns.filter((r) => Date.parse(r.createdAt) >= sinceMs);
34012
34153
  if (untilMs !== null) projectRuns = projectRuns.filter((r) => Date.parse(r.createdAt) <= untilMs);
34013
34154
  if (lastRuns !== null) projectRuns = projectRuns.slice(0, lastRuns);
@@ -34020,7 +34161,7 @@ async function visibilityStatsRoutes(app) {
34020
34161
  citationState: querySnapshots.citationState,
34021
34162
  answerMentioned: querySnapshots.answerMentioned,
34022
34163
  createdAt: querySnapshots.createdAt
34023
- }).from(querySnapshots).where(inArray21(querySnapshots.runId, runIds)).all() : [];
34164
+ }).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
34024
34165
  const stats = computeVisibilityStats({ queries: projectQueries, snapshots, groupBy });
34025
34166
  const queryAttribution = buildQueryAttribution(projectQueries);
34026
34167
  let shareOfVoice;
@@ -34031,7 +34172,7 @@ async function visibilityStatsRoutes(app) {
34031
34172
  queryText: querySnapshots.queryText,
34032
34173
  answerMentioned: querySnapshots.answerMentioned,
34033
34174
  answerText: querySnapshots.answerText
34034
- }).from(querySnapshots).where(inArray21(querySnapshots.runId, runIds)).all() : [];
34175
+ }).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
34035
34176
  const attributedSovSnapshots = sovSnapshots.filter((s) => resolveCurrentQuery(queryAttribution, s) !== void 0);
34036
34177
  const advanced = activeMeasurementPlan(app.db, project.id)?.plan.schemaVersion === 2;
34037
34178
  const queryClass = advanced || projectQueryClassifier(project) ? requestedQueryClass : "all";
@@ -34128,7 +34269,7 @@ function readVisibilityCompare(db, projectName, query) {
34128
34269
  answerText: querySnapshots.answerText,
34129
34270
  citedDomains: querySnapshots.citedDomains,
34130
34271
  location: querySnapshots.location
34131
- }).from(querySnapshots).where(inArray21(querySnapshots.runId, runIds)).all() : [];
34272
+ }).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
34132
34273
  return {
34133
34274
  runCount: runIds.length,
34134
34275
  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)))
@@ -34239,7 +34380,7 @@ function readVisibilityContinuity(db, projectName, months) {
34239
34380
  const trackedQueries = db.select({ id: queries.id, query: queries.query }).from(queries).where(eq44(queries.projectId, project.id)).all();
34240
34381
  const loadProjectMonth = (bounds) => {
34241
34382
  const runIds = legacyCompareRunIds(db, project.id, bounds);
34242
- 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() : [];
34383
+ 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() : [];
34243
34384
  return { runCount: runIds.length, snapshots: rows.map(bare) };
34244
34385
  };
34245
34386
  const frames = [{ frame: "project", continuity: gate(trackedQueries, loadProjectMonth(fromBounds), loadProjectMonth(toBounds)) }];
@@ -34496,7 +34637,7 @@ async function resultsExportRoutes(app) {
34496
34637
  }
34497
34638
 
34498
34639
  // ../api-routes/src/composites.ts
34499
- 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";
34640
+ 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";
34500
34641
 
34501
34642
  // ../api-routes/src/gsc-totals.ts
34502
34643
  import { and as and40, asc as asc7, eq as eq46, sql as sql17, max, min } from "drizzle-orm";
@@ -34772,7 +34913,7 @@ async function compositeRoutes(app, options) {
34772
34913
  const project = resolveProject(app.db, request.params.name);
34773
34914
  const filterLocation = (request.query.location ?? "").trim() || null;
34774
34915
  const sinceIso = parseSinceFilter(request.query.since);
34775
- const allRunsRaw = app.db.select().from(runs).where(and41(eq47(runs.projectId, project.id), notProbeRun())).orderBy(desc22(runs.createdAt), desc22(runs.id)).all();
34916
+ const allRunsRaw = app.db.select().from(runs).where(and41(eq47(runs.projectId, project.id), notProbeRun())).orderBy(desc23(runs.createdAt), desc23(runs.id)).all();
34776
34917
  const allRuns = allRunsRaw.filter((r) => runMatchesFilters(r, filterLocation, sinceIso));
34777
34918
  const totalRuns = allRuns.length;
34778
34919
  const visibilityRuns = allRuns.filter((r) => r.kind === RunKinds["answer-visibility"]);
@@ -34785,9 +34926,9 @@ async function compositeRoutes(app, options) {
34785
34926
  const previousVisibilityRun = pickGroupRepresentative(previousVisRunGroup);
34786
34927
  const latestRunRow = allRuns[0] ?? null;
34787
34928
  const latestRun = latestRunRow ? { totalRuns, run: summarizeRun(latestRunRow) } : { totalRuns: 0, run: null };
34788
- const healthRow = app.db.select().from(healthSnapshots).where(eq47(healthSnapshots.projectId, project.id)).orderBy(desc22(healthSnapshots.createdAt)).limit(1).get();
34929
+ const healthRow = app.db.select().from(healthSnapshots).where(eq47(healthSnapshots.projectId, project.id)).orderBy(desc23(healthSnapshots.createdAt)).limit(1).get();
34789
34930
  const health = healthRow ? mapHealthRow2(healthRow) : null;
34790
- const insightRows = app.db.select().from(insights).where(eq47(insights.projectId, project.id)).orderBy(desc22(insights.createdAt)).all();
34931
+ const insightRows = app.db.select().from(insights).where(eq47(insights.projectId, project.id)).orderBy(desc23(insights.createdAt)).all();
34791
34932
  const topInsights = insightRows.filter((row) => !row.dismissed).slice(0, TOP_INSIGHT_LIMIT).map(mapInsightRow2);
34792
34933
  const sparklineRunIds = visibilityRuns.slice(0, DEFAULT_RUN_HISTORY_LIMIT).map((r) => r.id);
34793
34934
  const snapshotRunIds = new Set(sparklineRunIds);
@@ -34959,7 +35100,7 @@ async function compositeRoutes(app, options) {
34959
35100
  like4(queries.query, pattern)
34960
35101
  )
34961
35102
  )
34962
- ).orderBy(desc22(querySnapshots.createdAt)).limit(limit + 1).all());
35103
+ ).orderBy(desc23(querySnapshots.createdAt)).limit(limit + 1).all());
34963
35104
  const insightMatches = app.db.select().from(insights).where(
34964
35105
  and41(
34965
35106
  eq47(insights.projectId, project.id),
@@ -34970,7 +35111,7 @@ async function compositeRoutes(app, options) {
34970
35111
  sql18`${insights.cause} LIKE ${pattern} ESCAPE '\\'`
34971
35112
  )
34972
35113
  )
34973
- ).orderBy(desc22(insights.createdAt)).limit(limit + 1).all();
35114
+ ).orderBy(desc23(insights.createdAt)).limit(limit + 1).all();
34974
35115
  const hits = [];
34975
35116
  for (const row of snapshotMatches) {
34976
35117
  hits.push(buildSnapshotHit(row, rawQuery));
@@ -35042,7 +35183,7 @@ function loadSnapshotsByRunIds(app, runIds, queryIdByText) {
35042
35183
  rawResponse: querySnapshots.rawResponse,
35043
35184
  competitorOverlap: querySnapshots.competitorOverlap,
35044
35185
  citedDomains: querySnapshots.citedDomains
35045
- }).from(querySnapshots).where(inArray22(querySnapshots.runId, [...runIds])).all();
35186
+ }).from(querySnapshots).where(inArray23(querySnapshots.runId, [...runIds])).all();
35046
35187
  for (const row of rows) {
35047
35188
  const queryText = row.queryText?.trim() || null;
35048
35189
  let queryId;
@@ -35194,8 +35335,8 @@ function buildIndexCoverageScore(app, projectId) {
35194
35335
  tooltip,
35195
35336
  trend: []
35196
35337
  };
35197
- const gscRow = app.db.select().from(gscCoverageSnapshots).where(eq47(gscCoverageSnapshots.projectId, projectId)).orderBy(desc22(gscCoverageSnapshots.date)).limit(1).get();
35198
- const bingRow = app.db.select().from(bingCoverageSnapshots).where(eq47(bingCoverageSnapshots.projectId, projectId)).orderBy(desc22(bingCoverageSnapshots.date)).limit(1).get();
35338
+ const gscRow = app.db.select().from(gscCoverageSnapshots).where(eq47(gscCoverageSnapshots.projectId, projectId)).orderBy(desc23(gscCoverageSnapshots.date)).limit(1).get();
35339
+ const bingRow = app.db.select().from(bingCoverageSnapshots).where(eq47(bingCoverageSnapshots.projectId, projectId)).orderBy(desc23(bingCoverageSnapshots.date)).limit(1).get();
35199
35340
  const chosen = pickIndexCoverageRow(gscRow, bingRow);
35200
35341
  if (!chosen) return empty;
35201
35342
  const total = chosen.indexed + chosen.notIndexed;
@@ -35221,7 +35362,7 @@ function countGoogleDeindexedUrls(app, projectId) {
35221
35362
  url: gscUrlInspections.url,
35222
35363
  indexingState: gscUrlInspections.indexingState,
35223
35364
  inspectedAt: gscUrlInspections.inspectedAt
35224
- }).from(gscUrlInspections).where(eq47(gscUrlInspections.projectId, projectId)).orderBy(desc22(gscUrlInspections.inspectedAt)).all();
35365
+ }).from(gscUrlInspections).where(eq47(gscUrlInspections.projectId, projectId)).orderBy(desc23(gscUrlInspections.inspectedAt)).all();
35225
35366
  if (rows.length === 0) return 0;
35226
35367
  const canonicalUrl = (url) => url.replace(/^http:\/\//, "https://");
35227
35368
  const historyByUrl = /* @__PURE__ */ new Map();
@@ -35477,10 +35618,10 @@ function makeSnippet(text2, query) {
35477
35618
 
35478
35619
  // ../api-routes/src/content.ts
35479
35620
  import crypto24 from "crypto";
35480
- import { and as and43, desc as desc24, eq as eq49 } from "drizzle-orm";
35621
+ import { and as and43, desc as desc25, eq as eq49 } from "drizzle-orm";
35481
35622
 
35482
35623
  // ../api-routes/src/content-data.ts
35483
- import { and as and42, eq as eq48, desc as desc23, gte as gte13, inArray as inArray23, lte as lte12 } from "drizzle-orm";
35624
+ import { and as and42, eq as eq48, desc as desc24, gte as gte13, inArray as inArray24, lte as lte12 } from "drizzle-orm";
35484
35625
  var RECENT_RUNS_WINDOW = 5;
35485
35626
  function loadOrchestratorInput(db, project, locationFilter = void 0, gscWindowDays = DEFAULT_CONTENT_GSC_WINDOW_DAYS) {
35486
35627
  const projectId = project.id;
@@ -35620,12 +35761,12 @@ function listRecentAnswerVisibilityRunIds(db, projectId, limit, locationFilter)
35620
35761
  // Queued/running/failed/cancelled runs may have partial or no
35621
35762
  // snapshots; including them risks pointing latestRunId at a run with
35622
35763
  // no usable evidence.
35623
- inArray23(runs.status, [RunStatuses.completed, RunStatuses.partial]),
35764
+ inArray24(runs.status, [RunStatuses.completed, RunStatuses.partial]),
35624
35765
  // Probe runs are operator/agent test runs; they must not poison the
35625
35766
  // recent-runs window the content engine uses to recommend actions.
35626
35767
  notProbeRun()
35627
35768
  )
35628
- ).orderBy(desc23(runs.createdAt)).all();
35769
+ ).orderBy(desc24(runs.createdAt)).all();
35629
35770
  const filtered = locationFilter === void 0 ? rows : rows.filter((r) => (r.location ?? null) === locationFilter);
35630
35771
  return filtered.slice(0, limit).map((r) => r.id);
35631
35772
  }
@@ -35660,7 +35801,7 @@ function buildGaTrafficByPage(db, projectId, window) {
35660
35801
  return map;
35661
35802
  }
35662
35803
  function resolveContentGaWindow(db, projectId, windowDays2) {
35663
- const latest = db.select({ date: gaTrafficSnapshots.date }).from(gaTrafficSnapshots).where(eq48(gaTrafficSnapshots.projectId, projectId)).orderBy(desc23(gaTrafficSnapshots.date)).limit(1).get();
35804
+ const latest = db.select({ date: gaTrafficSnapshots.date }).from(gaTrafficSnapshots).where(eq48(gaTrafficSnapshots.projectId, projectId)).orderBy(desc24(gaTrafficSnapshots.date)).limit(1).get();
35664
35805
  if (!latest?.date) return null;
35665
35806
  const end = /* @__PURE__ */ new Date(`${latest.date}T00:00:00Z`);
35666
35807
  end.setUTCDate(end.getUTCDate() - (Math.max(1, windowDays2) - 1));
@@ -35688,7 +35829,7 @@ function buildCandidateQueries(opts) {
35688
35829
  const queryRows2 = opts.db.select({ id: queries.id, text: queries.query }).from(queries).where(eq48(queries.projectId, opts.projectId)).all();
35689
35830
  const queryIdByText = new Map(queryRows2.map((r) => [r.text, r.id]));
35690
35831
  const candidateQueryIds = opts.candidateQueryStrings.map((q) => queryIdByText.get(q)).filter((id) => Boolean(id));
35691
- const snapshotRows = filterTrackedSnapshots(opts.db.select().from(querySnapshots).where(inArray23(querySnapshots.runId, opts.recentRunIds)).all()).filter((r) => candidateQueryIds.includes(r.queryId));
35832
+ const snapshotRows = filterTrackedSnapshots(opts.db.select().from(querySnapshots).where(inArray24(querySnapshots.runId, opts.recentRunIds)).all()).filter((r) => candidateQueryIds.includes(r.queryId));
35692
35833
  const snapshotsByQuery = /* @__PURE__ */ new Map();
35693
35834
  for (const row of snapshotRows) {
35694
35835
  const list = snapshotsByQuery.get(row.queryId) ?? [];
@@ -36088,7 +36229,7 @@ async function contentRoutes(app, opts = {}) {
36088
36229
  const row = app.db.select().from(recommendationExplanations).where(and43(
36089
36230
  eq49(recommendationExplanations.projectId, project.id),
36090
36231
  eq49(recommendationExplanations.targetRef, request.params.targetRef)
36091
- )).orderBy(desc24(recommendationExplanations.generatedAt)).limit(1).get();
36232
+ )).orderBy(desc25(recommendationExplanations.generatedAt)).limit(1).get();
36092
36233
  if (!row) {
36093
36234
  return reply.status(404).send({ error: { code: "NOT_FOUND", message: "No cached explanation for this targetRef." } });
36094
36235
  }
@@ -36116,7 +36257,7 @@ async function contentRoutes(app, opts = {}) {
36116
36257
  const cached = app.db.select().from(recommendationExplanations).where(and43(
36117
36258
  eq49(recommendationExplanations.projectId, project.id),
36118
36259
  eq49(recommendationExplanations.targetRef, targetRef)
36119
- )).orderBy(desc24(recommendationExplanations.generatedAt)).limit(1).get();
36260
+ )).orderBy(desc25(recommendationExplanations.generatedAt)).limit(1).get();
36120
36261
  if (cached) return reply.send(formatExplanationRow(cached));
36121
36262
  }
36122
36263
  const result = await explainer({
@@ -36246,7 +36387,7 @@ async function contentRoutes(app, opts = {}) {
36246
36387
  });
36247
36388
  app.get("/projects/:name/content/domain-classifications", async (request) => {
36248
36389
  const project = resolveProject(app.db, request.params.name);
36249
- const rows = app.db.select().from(domainClassifications).where(eq49(domainClassifications.projectId, project.id)).orderBy(desc24(domainClassifications.hits)).all();
36390
+ const rows = app.db.select().from(domainClassifications).where(eq49(domainClassifications.projectId, project.id)).orderBy(desc25(domainClassifications.hits)).all();
36250
36391
  const response = {
36251
36392
  classifications: rows.map((r) => ({
36252
36393
  domain: r.domain,
@@ -36266,7 +36407,7 @@ function lookupCachedBrief(db, projectId, targetRef, promptVersion) {
36266
36407
  if (promptVersion !== void 0) {
36267
36408
  conditions.push(eq49(recommendationBriefs.promptVersion, promptVersion));
36268
36409
  }
36269
- return db.select().from(recommendationBriefs).where(and43(...conditions)).orderBy(desc24(recommendationBriefs.generatedAt)).limit(1).get();
36410
+ return db.select().from(recommendationBriefs).where(and43(...conditions)).orderBy(desc25(recommendationBriefs.generatedAt)).limit(1).get();
36270
36411
  }
36271
36412
  function parseLimitParam(raw) {
36272
36413
  if (raw === void 0) return void 0;
@@ -38832,7 +38973,11 @@ var routeCatalog = [
38832
38973
  location: stringSchema,
38833
38974
  allLocations: booleanSchema,
38834
38975
  noLocation: booleanSchema,
38835
- dispatchMode: dispatchModeRequestSchema
38976
+ dispatchMode: dispatchModeRequestSchema,
38977
+ force: {
38978
+ type: "boolean",
38979
+ description: "Queue the run even when it would be refused with PROVIDERS_FAILING. Admission only; never stored."
38980
+ }
38836
38981
  }
38837
38982
  }
38838
38983
  }
@@ -38843,7 +38988,9 @@ var routeCatalog = [
38843
38988
  400: errorResponse(
38844
38989
  '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).'
38845
38990
  ),
38846
- 422: errorResponse("Project has no tracked queries."),
38991
+ 422: errorResponse(
38992
+ `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.`
38993
+ ),
38847
38994
  409: errorResponse("Run already in progress."),
38848
38995
  503: errorResponse("No runnable answer provider is configured.")
38849
38996
  }
@@ -38897,7 +39044,11 @@ var routeCatalog = [
38897
39044
  properties: {
38898
39045
  kind: stringSchema,
38899
39046
  providers: stringArraySchema,
38900
- dispatchMode: dispatchModeRequestSchema
39047
+ dispatchMode: dispatchModeRequestSchema,
39048
+ force: {
39049
+ type: "boolean",
39050
+ description: "Queue projects that would be refused with PROVIDERS_FAILING. Admission only; never stored."
39051
+ }
38901
39052
  }
38902
39053
  }
38903
39054
  }
@@ -38906,7 +39057,7 @@ var routeCatalog = [
38906
39057
  responses: {
38907
39058
  // TODO: Add `TriggerAllRunsResponse` Zod schema in contracts.
38908
39059
  207: rawJsonResponse(
38909
- "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.",
39060
+ "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.",
38910
39061
  { type: "array", items: looseObjectSchema }
38911
39062
  ),
38912
39063
  400: errorResponse("Invalid request: an unknown provider name, or an unsupported run kind.")
@@ -44154,7 +44305,7 @@ function buildOperationId(method, path8) {
44154
44305
 
44155
44306
  // ../api-routes/src/keys.ts
44156
44307
  import crypto25 from "crypto";
44157
- import { desc as desc25, eq as eq50 } from "drizzle-orm";
44308
+ import { desc as desc26, eq as eq50 } from "drizzle-orm";
44158
44309
  var KEYS_WRITE_SCOPE = "keys.write";
44159
44310
  function toApiKeyDto(row, projectNames) {
44160
44311
  const scopes = Array.isArray(row.scopes) ? row.scopes : [];
@@ -44179,7 +44330,7 @@ async function keysRoutes(app) {
44179
44330
  app.get("/keys", async (request) => {
44180
44331
  requireAdminSession(request);
44181
44332
  const scopedProjectId = request.apiKey?.projectId;
44182
- 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();
44333
+ 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();
44183
44334
  const names = projectNameById(app.db);
44184
44335
  return { keys: rows.map((row) => toApiKeyDto(row, names)) };
44185
44336
  });
@@ -45181,7 +45332,7 @@ function formatNotification(row) {
45181
45332
 
45182
45333
  // ../api-routes/src/google.ts
45183
45334
  import crypto33 from "crypto";
45184
- import { eq as eq54, and as and45, desc as desc26, sql as sql19, inArray as inArray24 } from "drizzle-orm";
45335
+ import { eq as eq54, and as and45, desc as desc27, sql as sql19, inArray as inArray25 } from "drizzle-orm";
45185
45336
 
45186
45337
  // ../api-routes/src/gsc-period-comparison.ts
45187
45338
  var DAY_MS = 864e5;
@@ -47692,9 +47843,9 @@ async function googleRoutes(app, opts) {
47692
47843
  const limitVal = Math.max(parseInt(limit ?? "500", 10) || 0, 1);
47693
47844
  const offsetVal = Math.max(parseInt(offset ?? "0", 10) || 0, 0);
47694
47845
  const orderColumns = {
47695
- clicks: [desc26(gscSearchData.clicks), desc26(gscSearchData.date), gscSearchData.query],
47696
- impressions: [desc26(gscSearchData.impressions), desc26(gscSearchData.date), gscSearchData.query],
47697
- date: [desc26(gscSearchData.date), desc26(gscSearchData.clicks), gscSearchData.query]
47846
+ clicks: [desc27(gscSearchData.clicks), desc27(gscSearchData.date), gscSearchData.query],
47847
+ impressions: [desc27(gscSearchData.impressions), desc27(gscSearchData.date), gscSearchData.query],
47848
+ date: [desc27(gscSearchData.date), desc27(gscSearchData.clicks), gscSearchData.query]
47698
47849
  }[orderBy];
47699
47850
  const rows = app.db.select().from(gscSearchData).where(and45(...conditions)).orderBy(...orderColumns).limit(limitVal).offset(offsetVal).all();
47700
47851
  const totalMatching = app.db.select({ total: sql19`COUNT(*)` }).from(gscSearchData).where(and45(...conditions)).get()?.total ?? 0;
@@ -47853,7 +48004,7 @@ async function googleRoutes(app, opts) {
47853
48004
  page: gscSearchData.page,
47854
48005
  clicks: sql19`COALESCE(SUM(${gscSearchData.clicks}), 0)`,
47855
48006
  impressions: sql19`COALESCE(SUM(${gscSearchData.impressions}), 0)`
47856
- }).from(gscSearchData).where(and45(...conditions)).groupBy(gscSearchData.page).orderBy(desc26(sql19`SUM(${gscSearchData.clicks})`), desc26(sql19`SUM(${gscSearchData.impressions})`)).limit(limitVal).all();
48007
+ }).from(gscSearchData).where(and45(...conditions)).groupBy(gscSearchData.page).orderBy(desc27(sql19`SUM(${gscSearchData.clicks})`), desc27(sql19`SUM(${gscSearchData.impressions})`)).limit(limitVal).all();
47857
48008
  const windowStart = startDate ?? cutoffDate ?? "";
47858
48009
  const windowEnd = endDate ?? resolvedWindow.endDate ?? "9999-12-31";
47859
48010
  const dailyTotals = readGscDailyTotals(app.db, project.id, windowStart, windowEnd);
@@ -47996,7 +48147,7 @@ async function googleRoutes(app, opts) {
47996
48147
  const { url, limit } = request.query;
47997
48148
  const conditions = [eq54(gscUrlInspections.projectId, project.id)];
47998
48149
  if (url) conditions.push(eq54(gscUrlInspections.url, url));
47999
- const rows = app.db.select().from(gscUrlInspections).where(and45(...conditions)).orderBy(desc26(gscUrlInspections.inspectedAt)).limit(parseInt(limit ?? "100", 10)).all();
48150
+ const rows = app.db.select().from(gscUrlInspections).where(and45(...conditions)).orderBy(desc27(gscUrlInspections.inspectedAt)).limit(parseInt(limit ?? "100", 10)).all();
48000
48151
  return rows.map((r) => ({
48001
48152
  id: r.id,
48002
48153
  url: r.url,
@@ -48015,7 +48166,7 @@ async function googleRoutes(app, opts) {
48015
48166
  });
48016
48167
  app.get("/projects/:name/google/gsc/deindexed", async (request) => {
48017
48168
  const project = resolveProject(app.db, request.params.name);
48018
- const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc26(gscUrlInspections.inspectedAt)).all();
48169
+ const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc27(gscUrlInspections.inspectedAt)).all();
48019
48170
  const byUrl = /* @__PURE__ */ new Map();
48020
48171
  for (const row of allInspections) {
48021
48172
  const existing = byUrl.get(row.url);
@@ -48043,7 +48194,7 @@ async function googleRoutes(app, opts) {
48043
48194
  });
48044
48195
  app.get("/projects/:name/google/gsc/coverage", async (request) => {
48045
48196
  const project = resolveProject(app.db, request.params.name);
48046
- const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc26(gscUrlInspections.inspectedAt)).all();
48197
+ const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc27(gscUrlInspections.inspectedAt)).all();
48047
48198
  const canonicalUrl = (url) => url.replace(/^http:\/\//, "https://");
48048
48199
  const latestByUrl = /* @__PURE__ */ new Map();
48049
48200
  const historyByUrl = /* @__PURE__ */ new Map();
@@ -48092,7 +48243,7 @@ async function googleRoutes(app, opts) {
48092
48243
  const total = latestByUrl.size;
48093
48244
  const indexed = indexedUrls.length;
48094
48245
  const notIndexed = notIndexedUrls.length;
48095
- const latestSnapshot = app.db.select({ createdAt: gscCoverageSnapshots.createdAt }).from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc26(gscCoverageSnapshots.createdAt)).limit(1).get();
48246
+ const latestSnapshot = app.db.select({ createdAt: gscCoverageSnapshots.createdAt }).from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc27(gscCoverageSnapshots.createdAt)).limit(1).get();
48096
48247
  const lastSyncedAt = latestSnapshot?.createdAt ?? null;
48097
48248
  const formatRow = (r) => ({
48098
48249
  id: r.id,
@@ -48148,7 +48299,7 @@ async function googleRoutes(app, opts) {
48148
48299
  const project = resolveProject(app.db, request.params.name);
48149
48300
  const parsed = parseInt(request.query.limit ?? "90", 10);
48150
48301
  const limit = Number.isNaN(parsed) || parsed <= 0 ? 90 : parsed;
48151
- const rows = app.db.select().from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc26(gscCoverageSnapshots.date)).limit(limit).all();
48302
+ const rows = app.db.select().from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc27(gscCoverageSnapshots.date)).limit(limit).all();
48152
48303
  return rows.map((r) => ({
48153
48304
  date: r.date,
48154
48305
  indexed: r.indexed,
@@ -48362,7 +48513,7 @@ async function googleRoutes(app, opts) {
48362
48513
  const { accessToken } = await getValidToken(store, project.canonicalDomain, "gsc", googleClientId, googleClientSecret);
48363
48514
  let urlsToNotify = request.body?.urls ?? [];
48364
48515
  if (request.body?.allUnindexed) {
48365
- const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc26(gscUrlInspections.inspectedAt)).all();
48516
+ const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc27(gscUrlInspections.inspectedAt)).all();
48366
48517
  const latestByUrl = /* @__PURE__ */ new Map();
48367
48518
  for (const row of allInspections) {
48368
48519
  if (!latestByUrl.has(row.url)) {
@@ -48729,7 +48880,7 @@ async function googleRoutes(app, opts) {
48729
48880
  const conditions = [eq54(gbpDailyMetrics.projectId, project.id)];
48730
48881
  if (request.query.locationName) conditions.push(eq54(gbpDailyMetrics.locationName, request.query.locationName));
48731
48882
  if (request.query.metric) conditions.push(eq54(gbpDailyMetrics.metric, request.query.metric));
48732
- const rows = app.db.select().from(gbpDailyMetrics).where(and45(...conditions)).orderBy(desc26(gbpDailyMetrics.date)).all();
48883
+ const rows = app.db.select().from(gbpDailyMetrics).where(and45(...conditions)).orderBy(desc27(gbpDailyMetrics.date)).all();
48733
48884
  return {
48734
48885
  metrics: rows.map((r) => ({ locationName: r.locationName, date: r.date, metric: r.metric, value: r.value })),
48735
48886
  total: rows.length
@@ -48776,7 +48927,7 @@ async function googleRoutes(app, opts) {
48776
48927
  const project = resolveProject(app.db, request.params.name);
48777
48928
  const conditions = [eq54(gbpLodgingSnapshots.projectId, project.id)];
48778
48929
  if (request.query.locationName) conditions.push(eq54(gbpLodgingSnapshots.locationName, request.query.locationName));
48779
- const rows = app.db.select().from(gbpLodgingSnapshots).where(and45(...conditions)).orderBy(desc26(gbpLodgingSnapshots.syncedAt)).all();
48930
+ const rows = app.db.select().from(gbpLodgingSnapshots).where(and45(...conditions)).orderBy(desc27(gbpLodgingSnapshots.syncedAt)).all();
48780
48931
  const latestByLocation = /* @__PURE__ */ new Map();
48781
48932
  for (const row of rows) {
48782
48933
  if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
@@ -48793,7 +48944,7 @@ async function googleRoutes(app, opts) {
48793
48944
  const project = resolveProject(app.db, request.params.name);
48794
48945
  const conditions = [eq54(gbpAttributesSnapshots.projectId, project.id)];
48795
48946
  if (request.query.locationName) conditions.push(eq54(gbpAttributesSnapshots.locationName, request.query.locationName));
48796
- const rows = app.db.select().from(gbpAttributesSnapshots).where(and45(...conditions)).orderBy(desc26(gbpAttributesSnapshots.syncedAt)).all();
48947
+ const rows = app.db.select().from(gbpAttributesSnapshots).where(and45(...conditions)).orderBy(desc27(gbpAttributesSnapshots.syncedAt)).all();
48797
48948
  const latestByLocation = /* @__PURE__ */ new Map();
48798
48949
  for (const row of rows) {
48799
48950
  if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
@@ -48813,7 +48964,7 @@ async function googleRoutes(app, opts) {
48813
48964
  const project = resolveProject(app.db, request.params.name);
48814
48965
  const conditions = [eq54(gbpPlaceDetails.projectId, project.id)];
48815
48966
  if (request.query.locationName) conditions.push(eq54(gbpPlaceDetails.locationName, request.query.locationName));
48816
- const rows = app.db.select().from(gbpPlaceDetails).where(and45(...conditions)).orderBy(desc26(gbpPlaceDetails.syncedAt)).all();
48967
+ const rows = app.db.select().from(gbpPlaceDetails).where(and45(...conditions)).orderBy(desc27(gbpPlaceDetails.syncedAt)).all();
48817
48968
  const latestByLocation = /* @__PURE__ */ new Map();
48818
48969
  for (const row of rows) {
48819
48970
  if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
@@ -48840,7 +48991,7 @@ async function googleRoutes(app, opts) {
48840
48991
  locationName ? eq54(gbpLocations.locationName, locationName) : eq54(gbpLocations.selected, true)
48841
48992
  )).orderBy(gbpLocations.displayName).all();
48842
48993
  const latestRating = /* @__PURE__ */ new Map();
48843
- for (const row of app.db.select().from(gbpReviewRatings).where(eq54(gbpReviewRatings.projectId, project.id)).orderBy(desc26(gbpReviewRatings.observedAt)).all()) {
48994
+ for (const row of app.db.select().from(gbpReviewRatings).where(eq54(gbpReviewRatings.projectId, project.id)).orderBy(desc27(gbpReviewRatings.observedAt)).all()) {
48844
48995
  if (!latestRating.has(row.locationName)) latestRating.set(row.locationName, row);
48845
48996
  }
48846
48997
  const locations = locationRows.map((loc) => {
@@ -48861,7 +49012,7 @@ async function googleRoutes(app, opts) {
48861
49012
  if (locationName) conditions.push(eq54(gbpReviews.locationName, locationName));
48862
49013
  if (negativeOnly) conditions.push(sql19`${gbpReviews.starRating} BETWEEN 1 AND ${negativeMaxStars}`);
48863
49014
  const total = app.db.select({ n: sql19`count(*)` }).from(gbpReviews).where(and45(...conditions)).get()?.n ?? 0;
48864
- const reviews = app.db.select().from(gbpReviews).where(and45(...conditions)).orderBy(desc26(gbpReviews.updateTime), gbpReviews.reviewName).limit(limit).all().map((r) => ({
49015
+ const reviews = app.db.select().from(gbpReviews).where(and45(...conditions)).orderBy(desc27(gbpReviews.updateTime), gbpReviews.reviewName).limit(limit).all().map((r) => ({
48865
49016
  locationName: r.locationName,
48866
49017
  origin: r.origin,
48867
49018
  reviewName: r.reviewName,
@@ -48900,10 +49051,10 @@ async function googleRoutes(app, opts) {
48900
49051
  locationProfiles: []
48901
49052
  });
48902
49053
  }
48903
- const metricRows = app.db.select().from(gbpDailyMetrics).where(and45(eq54(gbpDailyMetrics.projectId, project.id), inArray24(gbpDailyMetrics.locationName, locationNames))).all();
48904
- const keywordRows = app.db.select().from(gbpKeywordImpressions).where(and45(eq54(gbpKeywordImpressions.projectId, project.id), inArray24(gbpKeywordImpressions.locationName, locationNames))).all();
48905
- const placeActionRows = app.db.select().from(gbpPlaceActions).where(and45(eq54(gbpPlaceActions.projectId, project.id), inArray24(gbpPlaceActions.locationName, locationNames))).all();
48906
- const lodgingRows = app.db.select().from(gbpLodgingSnapshots).where(and45(eq54(gbpLodgingSnapshots.projectId, project.id), inArray24(gbpLodgingSnapshots.locationName, locationNames))).orderBy(desc26(gbpLodgingSnapshots.syncedAt)).all();
49054
+ const metricRows = app.db.select().from(gbpDailyMetrics).where(and45(eq54(gbpDailyMetrics.projectId, project.id), inArray25(gbpDailyMetrics.locationName, locationNames))).all();
49055
+ const keywordRows = app.db.select().from(gbpKeywordImpressions).where(and45(eq54(gbpKeywordImpressions.projectId, project.id), inArray25(gbpKeywordImpressions.locationName, locationNames))).all();
49056
+ const placeActionRows = app.db.select().from(gbpPlaceActions).where(and45(eq54(gbpPlaceActions.projectId, project.id), inArray25(gbpPlaceActions.locationName, locationNames))).all();
49057
+ const lodgingRows = app.db.select().from(gbpLodgingSnapshots).where(and45(eq54(gbpLodgingSnapshots.projectId, project.id), inArray25(gbpLodgingSnapshots.locationName, locationNames))).orderBy(desc27(gbpLodgingSnapshots.syncedAt)).all();
48907
49058
  const latestLodgingByLocation = /* @__PURE__ */ new Map();
48908
49059
  for (const row of lodgingRows) {
48909
49060
  if (!latestLodgingByLocation.has(row.locationName)) {
@@ -48917,7 +49068,7 @@ async function googleRoutes(app, opts) {
48917
49068
  regularHours: gbpLocations.regularHours,
48918
49069
  primaryPhone: gbpLocations.primaryPhone,
48919
49070
  openStatus: gbpLocations.openStatus
48920
- }).from(gbpLocations).where(and45(eq54(gbpLocations.projectId, project.id), inArray24(gbpLocations.locationName, locationNames))).all();
49071
+ }).from(gbpLocations).where(and45(eq54(gbpLocations.projectId, project.id), inArray25(gbpLocations.locationName, locationNames))).all();
48921
49072
  return buildGbpSummary({
48922
49073
  locationName,
48923
49074
  locationCount: locationNames.length,
@@ -48948,7 +49099,7 @@ function parseReviewLimit(value) {
48948
49099
 
48949
49100
  // ../api-routes/src/google-marketing.ts
48950
49101
  import crypto34 from "crypto";
48951
- 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";
49102
+ 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";
48952
49103
  import { z as z4 } from "zod";
48953
49104
  var snapshotPageQuerySchema = z4.object({
48954
49105
  limit: z4.coerce.number().int().min(1).max(GOOGLE_MARKETING_STORED_SNAPSHOT_PAGE_MAX).optional(),
@@ -50164,7 +50315,7 @@ async function googleMarketingRoutes(app, opts) {
50164
50315
  eq55(runs.projectId, project.id),
50165
50316
  eq55(runs.kind, RunKinds["google-ads-sync"]),
50166
50317
  or13(eq55(runs.status, RunStatuses.queued), eq55(runs.status, RunStatuses.running))
50167
- )).orderBy(desc27(runs.createdAt)).get();
50318
+ )).orderBy(desc28(runs.createdAt)).get();
50168
50319
  if (existing) {
50169
50320
  run = existing;
50170
50321
  return;
@@ -50200,7 +50351,7 @@ async function googleMarketingRoutes(app, opts) {
50200
50351
  eq55(runs.projectId, project.id),
50201
50352
  eq55(runs.kind, RunKinds["gtm-sync"]),
50202
50353
  or13(eq55(runs.status, RunStatuses.queued), eq55(runs.status, RunStatuses.running))
50203
- )).orderBy(desc27(runs.createdAt)).get();
50354
+ )).orderBy(desc28(runs.createdAt)).get();
50204
50355
  if (existing) {
50205
50356
  run = existing;
50206
50357
  return;
@@ -50235,7 +50386,7 @@ async function googleMarketingRoutes(app, opts) {
50235
50386
  ));
50236
50387
  }
50237
50388
  const limit = query.limit ?? 50;
50238
- const rows = app.db.select().from(googleAdsRawSnapshots).where(and46(...conditions)).orderBy(desc27(googleAdsRawSnapshots.capturedAt), desc27(googleAdsRawSnapshots.id)).limit(limit + 1).all();
50389
+ const rows = app.db.select().from(googleAdsRawSnapshots).where(and46(...conditions)).orderBy(desc28(googleAdsRawSnapshots.capturedAt), desc28(googleAdsRawSnapshots.id)).limit(limit + 1).all();
50239
50390
  const page3 = rows.slice(0, limit);
50240
50391
  const total = app.db.select({ total: sql20`COUNT(*)`.mapWith(Number).as("total") }).from(googleAdsRawSnapshots).where(eq55(googleAdsRawSnapshots.projectId, project.id)).get();
50241
50392
  return {
@@ -50267,7 +50418,7 @@ async function googleMarketingRoutes(app, opts) {
50267
50418
  ));
50268
50419
  }
50269
50420
  const limit = query.limit ?? 50;
50270
- const rows = app.db.select().from(gtmRawSnapshots).where(and46(...conditions)).orderBy(desc27(gtmRawSnapshots.capturedAt), desc27(gtmRawSnapshots.id)).limit(limit + 1).all();
50421
+ const rows = app.db.select().from(gtmRawSnapshots).where(and46(...conditions)).orderBy(desc28(gtmRawSnapshots.capturedAt), desc28(gtmRawSnapshots.id)).limit(limit + 1).all();
50271
50422
  const page3 = rows.slice(0, limit);
50272
50423
  const total = app.db.select({ total: sql20`COUNT(*)`.mapWith(Number).as("total") }).from(gtmRawSnapshots).where(eq55(gtmRawSnapshots.projectId, project.id)).get();
50273
50424
  return {
@@ -50538,7 +50689,7 @@ async function googleMarketingRoutes(app, opts) {
50538
50689
 
50539
50690
  // ../api-routes/src/ads.ts
50540
50691
  import crypto37 from "crypto";
50541
- 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";
50692
+ 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";
50542
50693
 
50543
50694
  // ../api-routes/src/ads-activation.ts
50544
50695
  import crypto35 from "crypto";
@@ -51924,7 +52075,7 @@ async function executeApprovedAdsActivation(dependencies, request) {
51924
52075
 
51925
52076
  // ../api-routes/src/ads-activation-routes.ts
51926
52077
  import crypto36 from "crypto";
51927
- 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";
52078
+ 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";
51928
52079
  var MAX_ACTIVATION_GRANT_LIFETIME_MS = 24 * 60 * 60 * 1e3;
51929
52080
  var ACTIVATION_LEASE_MS = 5 * 6e4;
51930
52081
  var ACTIVATION_REVOCATION_SETTLEMENT_MS = ACTIVATION_LEASE_MS;
@@ -52145,7 +52296,7 @@ function createActivationStore(app, request) {
52145
52296
  eq56(adsOperations.id, input.operationId),
52146
52297
  eq56(adsOperations.state, AdsOperationStates.pending),
52147
52298
  eq56(adsOperations.leaseOwner, input.leaseOwner),
52148
- gt4(adsOperations.leaseExpiresAt, input.now)
52299
+ gt5(adsOperations.leaseExpiresAt, input.now)
52149
52300
  )).run();
52150
52301
  const operation = loadActivationOperation(tx, input.operationId);
52151
52302
  if (!operation) throw internalError("Ads activation receipt was not found");
@@ -52201,7 +52352,7 @@ function createActivationStore(app, request) {
52201
52352
  eq56(adsOperations.id, input.operationId),
52202
52353
  eq56(adsOperations.state, AdsOperationStates.pending),
52203
52354
  eq56(adsOperations.leaseOwner, input.leaseOwner),
52204
- gt4(adsOperations.leaseExpiresAt, input.next.updatedAt)
52355
+ gt5(adsOperations.leaseExpiresAt, input.next.updatedAt)
52205
52356
  )).run();
52206
52357
  if (lease.changes !== 1 || existing.state !== input.fromState) {
52207
52358
  const current2 = loadActivationOperation(tx, input.operationId);
@@ -52243,7 +52394,7 @@ function createActivationStore(app, request) {
52243
52394
  eq56(adsOperations.id, input.operationId),
52244
52395
  eq56(adsOperations.state, AdsOperationStates.pending),
52245
52396
  eq56(adsOperations.leaseOwner, input.leaseOwner),
52246
- gt4(adsOperations.leaseExpiresAt, input.next.updatedAt)
52397
+ gt5(adsOperations.leaseExpiresAt, input.next.updatedAt)
52247
52398
  )).run();
52248
52399
  if (lease.changes !== 1 || existing.state !== input.fromState) {
52249
52400
  const operation2 = loadActivationOperation(tx, input.operationId);
@@ -52306,7 +52457,7 @@ function createActivationStore(app, request) {
52306
52457
  eq56(adsOperations.id, input.operationId),
52307
52458
  eq56(adsOperations.state, AdsOperationStates.pending),
52308
52459
  eq56(adsOperations.leaseOwner, input.leaseOwner),
52309
- gt4(adsOperations.leaseExpiresAt, input.now)
52460
+ gt5(adsOperations.leaseExpiresAt, input.now)
52310
52461
  )).run();
52311
52462
  if (operationUpdate.changes === 1) {
52312
52463
  const grantUpdate = tx.update(adsActivationGrants).set({
@@ -53582,7 +53733,7 @@ function semanticallyMatchesMaterializedEntity(app, input) {
53582
53733
  eq57(adsOperations.projectId, input.projectId),
53583
53734
  eq57(adsOperations.entityType, input.entityType),
53584
53735
  eq57(adsOperations.entityId, input.entityId),
53585
- inArray25(adsOperations.kind, [createKind, updateKind])
53736
+ inArray26(adsOperations.kind, [createKind, updateKind])
53586
53737
  )).orderBy(asc11(adsOperations.createdAt), asc11(adsOperations.id)).all();
53587
53738
  if (rows.some((row) => row.state === AdsOperationStates.pending || row.state === AdsOperationStates.reconciling || row.state === AdsOperationStates.unknown || row.kind === updateKind && row.state === AdsOperationStates.succeeded)) {
53588
53739
  return false;
@@ -54019,7 +54170,7 @@ function quarantineExhaustedReconciliation(app, row, now, policy, context) {
54019
54170
  eq57(adsOperations.id, row.id),
54020
54171
  eq57(adsOperations.projectId, row.projectId),
54021
54172
  gte14(adsOperations.reconcileAttempts, policy.maxAttempts),
54022
- inArray25(adsOperations.state, [
54173
+ inArray26(adsOperations.state, [
54023
54174
  AdsOperationStates.pending,
54024
54175
  AdsOperationStates.unknown,
54025
54176
  AdsOperationStates.reconciling
@@ -54243,7 +54394,7 @@ async function sweepAdsOperationsOnce(app, opts, config) {
54243
54394
  eq57(adsOperations.reconcileStrategy, AdsReconcileStrategies.create_fingerprint),
54244
54395
  or15(
54245
54396
  isNotNull7(adsOperations.entityId),
54246
- inArray25(adsOperations.state, [
54397
+ inArray26(adsOperations.state, [
54247
54398
  AdsOperationStates.pending,
54248
54399
  AdsOperationStates.reconciling
54249
54400
  ])
@@ -54291,7 +54442,7 @@ async function sweepAdsOperationsOnce(app, opts, config) {
54291
54442
  const eligibleProjectIds = [...credentialsByProjectId.keys()];
54292
54443
  if (eligibleProjectIds.length === 0) return;
54293
54444
  const rows = app.db.select().from(adsOperations).where(and48(
54294
- inArray25(adsOperations.projectId, eligibleProjectIds),
54445
+ inArray26(adsOperations.projectId, eligibleProjectIds),
54295
54446
  staleReconcileWhere
54296
54447
  )).orderBy(asc11(adsOperations.updatedAt)).limit(config.batchSize).all();
54297
54448
  for (const row of rows) {
@@ -54613,12 +54764,12 @@ async function adsRoutes(app, opts) {
54613
54764
  const cursor = parsed.data.cursor ? decodeAdsOperationCursor(parsed.data.cursor, project.id, parsed.data.state) : void 0;
54614
54765
  const rows = app.db.select().from(adsOperations).where(and48(
54615
54766
  eq57(adsOperations.projectId, project.id),
54616
- inArray25(adsOperations.state, parsed.data.state),
54767
+ inArray26(adsOperations.state, parsed.data.state),
54617
54768
  cursor ? or15(
54618
- gt5(adsOperations.createdAt, cursor.createdAt),
54769
+ gt6(adsOperations.createdAt, cursor.createdAt),
54619
54770
  and48(
54620
54771
  eq57(adsOperations.createdAt, cursor.createdAt),
54621
- gt5(adsOperations.id, cursor.id)
54772
+ gt6(adsOperations.id, cursor.id)
54622
54773
  )
54623
54774
  ) : void 0
54624
54775
  )).orderBy(asc11(adsOperations.createdAt), asc11(adsOperations.id)).limit(parsed.data.limit + 1).all();
@@ -55047,7 +55198,7 @@ async function adsRoutes(app, opts) {
55047
55198
  const inFlight = app.db.select({ id: runs.id, status: runs.status }).from(runs).where(and48(
55048
55199
  eq57(runs.projectId, project.id),
55049
55200
  eq57(runs.kind, RunKinds["ads-sync"]),
55050
- inArray25(runs.status, [RunStatuses.queued, RunStatuses.running])
55201
+ inArray26(runs.status, [RunStatuses.queued, RunStatuses.running])
55051
55202
  )).get();
55052
55203
  if (inFlight) {
55053
55204
  const existing = { runId: inFlight.id, status: inFlight.status };
@@ -55178,7 +55329,7 @@ async function adsRoutes(app, opts) {
55178
55329
  const latestAdsSync = app.db.select({ id: runs.id, kind: runs.kind, status: runs.status }).from(runs).where(and48(
55179
55330
  eq57(runs.projectId, project.id),
55180
55331
  eq57(runs.kind, RunKinds["ads-sync"])
55181
- )).orderBy(desc28(runs.createdAt)).get();
55332
+ )).orderBy(desc29(runs.createdAt)).get();
55182
55333
  const snapshot = storedSnapshotProvenance({
55183
55334
  connected: Boolean(connection),
55184
55335
  connectionLastSyncedAt: connection?.lastSyncedAt ?? null,
@@ -55582,7 +55733,7 @@ async function adsRoutes(app, opts) {
55582
55733
 
55583
55734
  // ../api-routes/src/bing.ts
55584
55735
  import crypto39 from "crypto";
55585
- import { eq as eq58, and as and49, desc as desc29 } from "drizzle-orm";
55736
+ import { eq as eq58, and as and49, desc as desc30 } from "drizzle-orm";
55586
55737
 
55587
55738
  // ../integration-bing/src/bing-client.ts
55588
55739
  import crypto38 from "crypto";
@@ -56001,7 +56152,7 @@ async function bingRoutes(app, opts) {
56001
56152
  const store = requireConnectionStore();
56002
56153
  const project = resolveProject(app.db, request.params.name);
56003
56154
  requireConnection(store, project.canonicalDomain);
56004
- const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc29(bingUrlInspections.inspectedAt)).all();
56155
+ const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc30(bingUrlInspections.inspectedAt)).all();
56005
56156
  const latestByUrl = /* @__PURE__ */ new Map();
56006
56157
  const definitiveByUrl = /* @__PURE__ */ new Map();
56007
56158
  for (const row of allInspections) {
@@ -56090,7 +56241,7 @@ async function bingRoutes(app, opts) {
56090
56241
  const project = resolveProject(app.db, request.params.name);
56091
56242
  const parsed = parseInt(request.query.limit ?? "90", 10);
56092
56243
  const limit = Number.isNaN(parsed) || parsed <= 0 ? 90 : parsed;
56093
- const rows = app.db.select().from(bingCoverageSnapshots).where(eq58(bingCoverageSnapshots.projectId, project.id)).orderBy(desc29(bingCoverageSnapshots.date)).limit(limit).all();
56244
+ const rows = app.db.select().from(bingCoverageSnapshots).where(eq58(bingCoverageSnapshots.projectId, project.id)).orderBy(desc30(bingCoverageSnapshots.date)).limit(limit).all();
56094
56245
  return rows.map((r) => ({
56095
56246
  date: r.date,
56096
56247
  indexed: r.indexed,
@@ -56103,7 +56254,7 @@ async function bingRoutes(app, opts) {
56103
56254
  const project = resolveProject(app.db, request.params.name);
56104
56255
  const { url, limit } = request.query;
56105
56256
  const whereClause = url ? and49(eq58(bingUrlInspections.projectId, project.id), eq58(bingUrlInspections.url, url)) : eq58(bingUrlInspections.projectId, project.id);
56106
- 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();
56257
+ 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();
56107
56258
  return filtered.map((r) => ({
56108
56259
  id: r.id,
56109
56260
  url: r.url,
@@ -56247,7 +56398,7 @@ async function bingRoutes(app, opts) {
56247
56398
  }
56248
56399
  let urlsToSubmit = request.body?.urls ?? [];
56249
56400
  if (request.body?.allUnindexed) {
56250
- const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc29(bingUrlInspections.inspectedAt)).all();
56401
+ const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc30(bingUrlInspections.inspectedAt)).all();
56251
56402
  const latestByUrl = /* @__PURE__ */ new Map();
56252
56403
  for (const row of allInspections) {
56253
56404
  if (!latestByUrl.has(row.url)) {
@@ -56506,7 +56657,7 @@ async function cdpRoutes(app, opts) {
56506
56657
 
56507
56658
  // ../api-routes/src/ga.ts
56508
56659
  import crypto40 from "crypto";
56509
- import { eq as eq60, desc as desc30, and as and51, sql as sql23 } from "drizzle-orm";
56660
+ import { eq as eq60, desc as desc31, and as and51, sql as sql23 } from "drizzle-orm";
56510
56661
 
56511
56662
  // ../api-routes/src/ga-session-history.ts
56512
56663
  function buildSessionHistory(landingPageDays, dailyTotals) {
@@ -56982,7 +57133,7 @@ async function ga4Routes(app, opts) {
56982
57133
  if (!connected) {
56983
57134
  return { connected: false, propertyId: null, clientEmail: null, authMethod: null, lastSyncedAt: null };
56984
57135
  }
56985
- const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc30(gaTrafficSummaries.syncedAt)).limit(1).get();
57136
+ const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc31(gaTrafficSummaries.syncedAt)).limit(1).get();
56986
57137
  return {
56987
57138
  connected: true,
56988
57139
  propertyId: saConn?.propertyId ?? oauthConn?.propertyId ?? null,
@@ -57412,7 +57563,7 @@ async function ga4Routes(app, opts) {
57412
57563
  const socialTotals = app.db.select({
57413
57564
  sessions: sql23`SUM(${gaSocialReferrals.sessions})`
57414
57565
  }).from(gaSocialReferrals).where(and51(...socialConditions)).get();
57415
- const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc30(gaTrafficSummaries.syncedAt)).limit(1).get();
57566
+ const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc31(gaTrafficSummaries.syncedAt)).limit(1).get();
57416
57567
  const total = summaryRow?.totalSessions ?? 0;
57417
57568
  const totalDirectSessions = directTotalRow?.totalDirectSessions ?? 0;
57418
57569
  const totalOrganicSessions = summaryRow?.totalOrganicSessions ?? 0;
@@ -59364,7 +59515,7 @@ async function wordpressRoutes(app, opts) {
59364
59515
 
59365
59516
  // ../api-routes/src/backlinks.ts
59366
59517
  import crypto42 from "crypto";
59367
- import { and as and53, asc as asc12, desc as desc31, eq as eq61, sql as sql24 } from "drizzle-orm";
59518
+ import { and as and53, asc as asc12, desc as desc32, eq as eq61, sql as sql24 } from "drizzle-orm";
59368
59519
 
59369
59520
  // ../integration-commoncrawl/src/constants.ts
59370
59521
  import os2 from "os";
@@ -59865,7 +60016,7 @@ function latestSummaryForProject(db, projectId, source, release) {
59865
60016
  eq61(backlinkSummaries.source, source)
59866
60017
  ];
59867
60018
  if (release) conditions.push(eq61(backlinkSummaries.release, release));
59868
- return db.select().from(backlinkSummaries).where(and53(...conditions)).orderBy(desc31(backlinkSummaries.queriedAt)).limit(1).get();
60019
+ return db.select().from(backlinkSummaries).where(and53(...conditions)).orderBy(desc32(backlinkSummaries.queriedAt)).limit(1).get();
59869
60020
  }
59870
60021
  function parseExcludeCrawlers(value) {
59871
60022
  if (!value) return false;
@@ -59887,7 +60038,7 @@ function computeFilteredSummary(db, base) {
59887
60038
  count: sql24`count(*)`,
59888
60039
  total: sql24`coalesce(sum(${backlinkDomains.numHosts}), 0)`
59889
60040
  }).from(backlinkDomains).where(filteredCondition).get();
59890
- const top10Rows = db.select({ numHosts: backlinkDomains.numHosts }).from(backlinkDomains).where(filteredCondition).orderBy(desc31(backlinkDomains.numHosts)).limit(10).all();
60041
+ const top10Rows = db.select({ numHosts: backlinkDomains.numHosts }).from(backlinkDomains).where(filteredCondition).orderBy(desc32(backlinkDomains.numHosts)).limit(10).all();
59891
60042
  const totalLinkingDomains = Number(filteredAgg?.count ?? 0);
59892
60043
  const totalHosts = Number(filteredAgg?.total ?? 0);
59893
60044
  const unfilteredLinkingDomains = Number(unfilteredAgg?.count ?? 0);
@@ -59908,7 +60059,7 @@ function computeFilteredSummary(db, base) {
59908
60059
  };
59909
60060
  }
59910
60061
  function buildSourceAvailability(db, projectId, source, connected, excludeCrawlers) {
59911
- const summary3 = db.select().from(backlinkSummaries).where(and53(eq61(backlinkSummaries.projectId, projectId), eq61(backlinkSummaries.source, source))).orderBy(desc31(backlinkSummaries.queriedAt)).limit(1).get();
60062
+ const summary3 = db.select().from(backlinkSummaries).where(and53(eq61(backlinkSummaries.projectId, projectId), eq61(backlinkSummaries.source, source))).orderBy(desc32(backlinkSummaries.queriedAt)).limit(1).get();
59912
60063
  let totalLinkingDomains = summary3?.totalLinkingDomains ?? 0;
59913
60064
  if (summary3 && excludeCrawlers) {
59914
60065
  const filtered = db.select({ count: sql24`count(*)` }).from(backlinkDomains).where(and53(
@@ -60013,11 +60164,11 @@ async function backlinksRoutes(app, opts) {
60013
60164
  return reply.status(201).send(mapSyncRow(inserted));
60014
60165
  });
60015
60166
  app.get("/backlinks/syncs/latest", async (_request, reply) => {
60016
- const row = app.db.select().from(ccReleaseSyncs).orderBy(desc31(ccReleaseSyncs.updatedAt)).limit(1).get();
60167
+ const row = app.db.select().from(ccReleaseSyncs).orderBy(desc32(ccReleaseSyncs.updatedAt)).limit(1).get();
60017
60168
  return reply.send(row ? mapSyncRow(row) : null);
60018
60169
  });
60019
60170
  app.get("/backlinks/syncs", async (_request, reply) => {
60020
- const rows = app.db.select().from(ccReleaseSyncs).orderBy(desc31(ccReleaseSyncs.updatedAt)).all();
60171
+ const rows = app.db.select().from(ccReleaseSyncs).orderBy(desc32(ccReleaseSyncs.updatedAt)).all();
60021
60172
  return reply.send(rows.map(mapSyncRow));
60022
60173
  });
60023
60174
  app.get("/backlinks/releases", async (_request, reply) => {
@@ -60104,7 +60255,7 @@ async function backlinksRoutes(app, opts) {
60104
60255
  linkingDomain: backlinkDomains.linkingDomain,
60105
60256
  numHosts: backlinkDomains.numHosts,
60106
60257
  source: backlinkDomains.source
60107
- }).from(backlinkDomains).where(domainCondition).orderBy(desc31(backlinkDomains.numHosts)).limit(limit).offset(offset).all();
60258
+ }).from(backlinkDomains).where(domainCondition).orderBy(desc32(backlinkDomains.numHosts)).limit(limit).offset(offset).all();
60108
60259
  let summary3 = null;
60109
60260
  if (summaryRow) {
60110
60261
  summary3 = excludeCrawlers ? computeFilteredSummary(app.db, summaryRow) : mapSummaryRow(summaryRow);
@@ -60150,7 +60301,7 @@ import crypto45 from "crypto";
60150
60301
  import { isIP } from "net";
60151
60302
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
60152
60303
  import { Agent as UndiciAgent } from "undici";
60153
- 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";
60304
+ 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";
60154
60305
 
60155
60306
  // ../api-routes/src/cloudflare-worker-version.ts
60156
60307
  var CURRENT_CLOUDFLARE_WORKER_VERSION = "1.0.1";
@@ -79892,7 +80043,7 @@ async function trafficRoutes(app, opts) {
79892
80043
  eq65(runs.kind, RunKinds["traffic-sync"]),
79893
80044
  eq65(runs.sourceId, row.id)
79894
80045
  )
79895
- ).orderBy(desc32(runs.startedAt)).limit(1).get();
80046
+ ).orderBy(desc33(runs.startedAt)).limit(1).get();
79896
80047
  return {
79897
80048
  ...rowToDto(row),
79898
80049
  totals24h: {
@@ -79971,14 +80122,14 @@ async function trafficRoutes(app, opts) {
79971
80122
  });
79972
80123
  app.get("/projects/:name/traffic/sources", async (request) => {
79973
80124
  const project = resolveProject(app.db, request.params.name);
79974
- const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc32(trafficSources.createdAt)).all();
80125
+ const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc33(trafficSources.createdAt)).all();
79975
80126
  const sources = rows.filter((row) => row.status !== TrafficSourceStatuses.archived).map(rowToDto);
79976
80127
  const response = { sources };
79977
80128
  return response;
79978
80129
  });
79979
80130
  app.get("/projects/:name/traffic/status", async (request) => {
79980
80131
  const project = resolveProject(app.db, request.params.name);
79981
- const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc32(trafficSources.createdAt)).all();
80132
+ const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc33(trafficSources.createdAt)).all();
79982
80133
  const since = new Date(Date.now() - 24 * 60 * 6e4).toISOString();
79983
80134
  const sources = rows.filter((row) => row.status !== TrafficSourceStatuses.archived).map((row) => buildSourceDetail(project.id, row, since));
79984
80135
  const response = { sources };
@@ -80089,7 +80240,7 @@ async function trafficRoutes(app, opts) {
80089
80240
  const listed = useContentList ? contentPaths : infraPaths;
80090
80241
  const IN_LIST_CAP = 2e4;
80091
80242
  const listFitsInSql = listed.length <= IN_LIST_CAP;
80092
- 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`;
80243
+ 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`;
80093
80244
  if (listFitsInSql) {
80094
80245
  const crawlerSeries = app.db.select({
80095
80246
  bucket: crawlerSeriesBucket,
@@ -80116,7 +80267,7 @@ async function trafficRoutes(app, opts) {
80116
80267
  if (useContentList ? inList : !inList) point.crawlerContentHits += hits;
80117
80268
  }
80118
80269
  }
80119
- const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(desc32(crawlerEventsHourly.tsHour)).limit(limit).all();
80270
+ const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(desc33(crawlerEventsHourly.tsHour)).limit(limit).all();
80120
80271
  for (const r of rows) {
80121
80272
  events.push({
80122
80273
  kind: TrafficEventKinds.crawler,
@@ -80156,7 +80307,7 @@ async function trafficRoutes(app, opts) {
80156
80307
  for (const row of userFetchSeries) {
80157
80308
  trafficSeriesPoint(seriesByBucket, row.bucket).aiUserFetchHits = Number(row.hits);
80158
80309
  }
80159
- const rows = app.db.select().from(aiUserFetchEventsHourly).where(userFetchWhere).orderBy(desc32(aiUserFetchEventsHourly.tsHour)).limit(limit).all();
80310
+ const rows = app.db.select().from(aiUserFetchEventsHourly).where(userFetchWhere).orderBy(desc33(aiUserFetchEventsHourly.tsHour)).limit(limit).all();
80160
80311
  for (const r of rows) {
80161
80312
  events.push({
80162
80313
  kind: TrafficEventKinds["ai-user-fetch"],
@@ -80209,7 +80360,7 @@ async function trafficRoutes(app, opts) {
80209
80360
  point.aiReferralHits = Number(row.hits);
80210
80361
  point.aiReferralLandedHits = Number(row.landed);
80211
80362
  }
80212
- const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(desc32(aiReferralEventsHourly.tsHour)).limit(limit).all();
80363
+ const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(desc33(aiReferralEventsHourly.tsHour)).limit(limit).all();
80213
80364
  for (const r of rows) {
80214
80365
  const counts2 = aiReferralClassCounts(r.sessionsOrHits, r.paidSessionsOrHits, r.organicSessionsOrHits);
80215
80366
  events.push({
@@ -80478,7 +80629,7 @@ var reportSweepsCheck = {
80478
80629
  };
80479
80630
 
80480
80631
  // ../api-routes/src/doctor/checks/report-models.ts
80481
- import { and as and59, eq as eq67, gte as gte18, inArray as inArray27, lte as lte19 } from "drizzle-orm";
80632
+ import { and as and59, eq as eq67, gte as gte18, inArray as inArray28, lte as lte19 } from "drizzle-orm";
80482
80633
  var reportModelsCheck = {
80483
80634
  id: "report.models",
80484
80635
  category: CheckCategories.providers,
@@ -80493,7 +80644,7 @@ var reportModelsCheck = {
80493
80644
  const months = reportMonths.flatMap((month) => {
80494
80645
  const bounds = calendarMonthBounds(month);
80495
80646
  const previous = new Date(Date.parse(bounds.since) - 1).toISOString().slice(0, 7);
80496
- 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();
80647
+ 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();
80497
80648
  return readVisibilityContinuity(ctx.db, ctx.project.name, { from: previous, to: month }).map(({ frame, continuity: continuity2 }) => ({
80498
80649
  month,
80499
80650
  previousMonth: previous,
@@ -81570,7 +81721,7 @@ var ga4ConnectionCheck = {
81570
81721
  var GA_AUTH_CHECKS = [ga4ConnectionCheck];
81571
81722
 
81572
81723
  // ../api-routes/src/doctor/checks/data-freshness.ts
81573
- import { and as and62, desc as desc33, eq as eq73, inArray as inArray28 } from "drizzle-orm";
81724
+ import { and as and62, desc as desc34, eq as eq73, inArray as inArray29 } from "drizzle-orm";
81574
81725
  var GA_DATA_AGING_DAYS = 3;
81575
81726
  var GA_DATA_STALE_DAYS = 5;
81576
81727
  var GSC_DATA_AGING_DAYS = 5;
@@ -81598,7 +81749,7 @@ function skipped(code, summary3) {
81598
81749
  return { status: CheckStatuses.skipped, code, summary: summary3, remediation: null };
81599
81750
  }
81600
81751
  function lastSyncAgeDays(ctx, kinds) {
81601
- 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();
81752
+ 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();
81602
81753
  if (!row?.createdAt) return null;
81603
81754
  const age = Math.floor((Date.now() - Date.parse(row.createdAt)) / DAY_MS2);
81604
81755
  return Number.isFinite(age) ? age : null;
@@ -81694,7 +81845,7 @@ var gaRecentDataCheck = {
81694
81845
  const connection = gaConnected(ctx);
81695
81846
  if (connection === "store-unavailable") return skipped("ga.data.store-unavailable", "No GA4 credential store configured for this deployment.");
81696
81847
  if (connection === "not-connected") return skipped("ga.data.not-connected", "GA4 is not connected for this project.");
81697
- const newest = ctx.db.select({ date: gaDailyTotals.date }).from(gaDailyTotals).where(eq73(gaDailyTotals.projectId, ctx.project.id)).orderBy(desc33(gaDailyTotals.date)).limit(1).get();
81848
+ const newest = ctx.db.select({ date: gaDailyTotals.date }).from(gaDailyTotals).where(eq73(gaDailyTotals.projectId, ctx.project.id)).orderBy(desc34(gaDailyTotals.date)).limit(1).get();
81698
81849
  return grade(ctx, GA_SPEC, newest?.date);
81699
81850
  }
81700
81851
  };
@@ -81711,7 +81862,7 @@ var gscRecentDataCheck = {
81711
81862
  }
81712
81863
  const watermark = ctx.db.select({ dataThroughDate: gscDataWatermarks.dataThroughDate }).from(gscDataWatermarks).where(eq73(gscDataWatermarks.projectId, ctx.project.id)).get();
81713
81864
  if (watermark?.dataThroughDate) return grade(ctx, GSC_SPEC, watermark.dataThroughDate);
81714
- const newest = ctx.db.select({ date: gscDailyTotals.date }).from(gscDailyTotals).where(eq73(gscDailyTotals.projectId, ctx.project.id)).orderBy(desc33(gscDailyTotals.date)).limit(1).get();
81865
+ const newest = ctx.db.select({ date: gscDailyTotals.date }).from(gscDailyTotals).where(eq73(gscDailyTotals.projectId, ctx.project.id)).orderBy(desc34(gscDailyTotals.date)).limit(1).get();
81715
81866
  return grade(ctx, GSC_SPEC, newest?.date);
81716
81867
  }
81717
81868
  };
@@ -82967,7 +83118,7 @@ var RUNTIME_STATE_CHECKS = [
82967
83118
  ];
82968
83119
 
82969
83120
  // ../api-routes/src/doctor/checks/traffic-source.ts
82970
- import { and as and65, eq as eq77, gte as gte19, inArray as inArray29, ne as ne14, sql as sql28 } from "drizzle-orm";
83121
+ import { and as and65, eq as eq77, gte as gte19, inArray as inArray30, ne as ne14, sql as sql28 } from "drizzle-orm";
82971
83122
  var RECENT_DATA_WARN_DAYS = 7;
82972
83123
  var RECENT_DATA_FAIL_DAYS = 30;
82973
83124
  function isCloudflareDirectPush(source) {
@@ -83115,7 +83266,7 @@ var recentDataCheck = {
83115
83266
  ctx.db.select({ total: sql28`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
83116
83267
  and65(
83117
83268
  eq77(crawlerEventsHourly.projectId, ctx.project.id),
83118
- inArray29(crawlerEventsHourly.sourceId, activeSourceIds),
83269
+ inArray30(crawlerEventsHourly.sourceId, activeSourceIds),
83119
83270
  gte19(crawlerEventsHourly.tsHour, warnCutoff)
83120
83271
  )
83121
83272
  ).get()?.total ?? 0
@@ -83124,7 +83275,7 @@ var recentDataCheck = {
83124
83275
  ctx.db.select({ total: sql28`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
83125
83276
  and65(
83126
83277
  eq77(aiReferralEventsHourly.projectId, ctx.project.id),
83127
- inArray29(aiReferralEventsHourly.sourceId, activeSourceIds),
83278
+ inArray30(aiReferralEventsHourly.sourceId, activeSourceIds),
83128
83279
  gte19(aiReferralEventsHourly.tsHour, warnCutoff)
83129
83280
  )
83130
83281
  ).get()?.total ?? 0
@@ -83133,7 +83284,7 @@ var recentDataCheck = {
83133
83284
  ctx.db.select({ total: sql28`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
83134
83285
  and65(
83135
83286
  eq77(aiUserFetchEventsHourly.projectId, ctx.project.id),
83136
- inArray29(aiUserFetchEventsHourly.sourceId, activeSourceIds),
83287
+ inArray30(aiUserFetchEventsHourly.sourceId, activeSourceIds),
83137
83288
  gte19(aiUserFetchEventsHourly.tsHour, warnCutoff)
83138
83289
  )
83139
83290
  ).get()?.total ?? 0
@@ -83159,7 +83310,7 @@ var recentDataCheck = {
83159
83310
  ctx.db.select({ total: sql28`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
83160
83311
  and65(
83161
83312
  eq77(crawlerEventsHourly.projectId, ctx.project.id),
83162
- inArray29(crawlerEventsHourly.sourceId, activeSourceIds),
83313
+ inArray30(crawlerEventsHourly.sourceId, activeSourceIds),
83163
83314
  gte19(crawlerEventsHourly.tsHour, failCutoff)
83164
83315
  )
83165
83316
  ).get()?.total ?? 0
@@ -83168,7 +83319,7 @@ var recentDataCheck = {
83168
83319
  ctx.db.select({ total: sql28`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
83169
83320
  and65(
83170
83321
  eq77(aiReferralEventsHourly.projectId, ctx.project.id),
83171
- inArray29(aiReferralEventsHourly.sourceId, activeSourceIds),
83322
+ inArray30(aiReferralEventsHourly.sourceId, activeSourceIds),
83172
83323
  gte19(aiReferralEventsHourly.tsHour, failCutoff)
83173
83324
  )
83174
83325
  ).get()?.total ?? 0
@@ -83177,7 +83328,7 @@ var recentDataCheck = {
83177
83328
  ctx.db.select({ total: sql28`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
83178
83329
  and65(
83179
83330
  eq77(aiUserFetchEventsHourly.projectId, ctx.project.id),
83180
- inArray29(aiUserFetchEventsHourly.sourceId, activeSourceIds),
83331
+ inArray30(aiUserFetchEventsHourly.sourceId, activeSourceIds),
83181
83332
  gte19(aiUserFetchEventsHourly.tsHour, failCutoff)
83182
83333
  )
83183
83334
  ).get()?.total ?? 0
@@ -84184,7 +84335,7 @@ async function doctorRoutes(app, opts) {
84184
84335
 
84185
84336
  // ../api-routes/src/discovery/routes.ts
84186
84337
  import crypto47 from "crypto";
84187
- 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";
84338
+ 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";
84188
84339
  var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
84189
84340
  async function discoveryRoutes(app, opts) {
84190
84341
  app.post("/projects/:name/discover/run", async (request, reply) => {
@@ -84239,13 +84390,13 @@ async function discoveryRoutes(app, opts) {
84239
84390
  // must never reuse another set's session. Null (= Gemini-only
84240
84391
  // default, including explicit ['gemini']) matches legacy rows.
84241
84392
  seedProviders == null ? isNull14(discoverySessions.seedProviders) : eq78(discoverySessions.seedProviders, seedProviders),
84242
- inArray30(discoverySessions.status, [
84393
+ inArray31(discoverySessions.status, [
84243
84394
  DiscoverySessionStatuses.queued,
84244
84395
  DiscoverySessionStatuses.seeding,
84245
84396
  DiscoverySessionStatuses.probing
84246
84397
  ]),
84247
84398
  gte20(discoverySessions.createdAt, ageFloorIso)
84248
- )).orderBy(desc34(discoverySessions.createdAt)).get();
84399
+ )).orderBy(desc35(discoverySessions.createdAt)).get();
84249
84400
  if (existing && existing.runId) {
84250
84401
  return { reused: true, sessionId: existing.id, runId: existing.runId };
84251
84402
  }
@@ -84314,7 +84465,7 @@ async function discoveryRoutes(app, opts) {
84314
84465
  const project = resolveProject(app.db, request.params.name);
84315
84466
  const parsedLimit = parseInt(request.query.limit ?? "", 10);
84316
84467
  const limit = Number.isNaN(parsedLimit) || parsedLimit <= 0 ? 50 : parsedLimit;
84317
- const rows = app.db.select().from(discoverySessions).where(eq78(discoverySessions.projectId, project.id)).orderBy(desc34(discoverySessions.createdAt)).limit(limit).all();
84468
+ const rows = app.db.select().from(discoverySessions).where(eq78(discoverySessions.projectId, project.id)).orderBy(desc35(discoverySessions.createdAt)).limit(limit).all();
84318
84469
  return reply.send(rows.map(serializeSession));
84319
84470
  }
84320
84471
  );
@@ -84938,7 +85089,7 @@ function dedupeStrings(input) {
84938
85089
 
84939
85090
  // ../api-routes/src/technical-aeo.ts
84940
85091
  import crypto49 from "crypto";
84941
- 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";
85092
+ 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";
84942
85093
  import { alias } from "drizzle-orm/sqlite-core";
84943
85094
  var FETCHED_SITE_CRAWL_STATES = /* @__PURE__ */ new Set([
84944
85095
  ...SiteCrawlFetchedStates,
@@ -85263,11 +85414,11 @@ async function technicalAeoRoutes(app, opts) {
85263
85414
  eq80(siteCrawlSnapshots.projectId, projectId),
85264
85415
  eq80(runs.projectId, projectId),
85265
85416
  eq80(runs.kind, RunKinds["site-audit"]),
85266
- inArray31(runs.status, SURFACEABLE_STATUSES),
85417
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85267
85418
  notProbeRun()
85268
85419
  ];
85269
85420
  if (runId) filters.push(eq80(siteCrawlSnapshots.runId, runId));
85270
- 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();
85421
+ 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();
85271
85422
  };
85272
85423
  const detailScopeFor = (projectId, snapshot) => snapshot.detailsAvailable && snapshot.attemptId ? { projectId, runId: snapshot.runId, attemptId: snapshot.attemptId } : null;
85273
85424
  const completenessOf = (snapshot) => ({
@@ -85294,7 +85445,7 @@ async function technicalAeoRoutes(app, opts) {
85294
85445
  eq80(runs.id, runId),
85295
85446
  eq80(runs.projectId, projectId),
85296
85447
  eq80(runs.kind, RunKinds["site-audit"]),
85297
- inArray31(runs.status, SURFACEABLE_STATUSES),
85448
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85298
85449
  notProbeRun()
85299
85450
  )).limit(1).get());
85300
85451
  const assertKnownAuditRun = (projectId, runId) => {
@@ -85304,7 +85455,7 @@ async function technicalAeoRoutes(app, opts) {
85304
85455
  eq80(siteAuditSnapshots.projectId, projectId),
85305
85456
  eq80(runs.projectId, projectId),
85306
85457
  eq80(runs.kind, RunKinds["site-audit"]),
85307
- inArray31(runs.status, SURFACEABLE_STATUSES),
85458
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85308
85459
  notProbeRun()
85309
85460
  )).limit(1).get());
85310
85461
  const emptyCrawlSummary = (projectName, legacyAuditAvailable) => ({
@@ -85328,17 +85479,17 @@ async function technicalAeoRoutes(app, opts) {
85328
85479
  eq80(siteAuditSnapshots.projectId, project.id),
85329
85480
  eq80(runs.projectId, project.id),
85330
85481
  eq80(runs.kind, RunKinds["site-audit"]),
85331
- inArray31(runs.status, SURFACEABLE_STATUSES),
85482
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85332
85483
  notProbeRun()
85333
85484
  ];
85334
85485
  const targetFilters = request.query.runId ? [...baseFilters, eq80(siteAuditSnapshots.runId, request.query.runId)] : baseFilters;
85335
- 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();
85486
+ 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();
85336
85487
  if (!latest) {
85337
85488
  if (request.query.runId) throw notFound("Site audit run", request.query.runId);
85338
85489
  return emptyScore(project.name);
85339
85490
  }
85340
85491
  const snap = latest.snap;
85341
- 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;
85492
+ 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;
85342
85493
  const deltaScore = previous ? snap.aggregateScore - previous.aggregateScore : null;
85343
85494
  const trend = deltaScore == null ? null : deltaScore > 0 ? SiteAuditTrendDirections.up : deltaScore < 0 ? SiteAuditTrendDirections.down : SiteAuditTrendDirections.flat;
85344
85495
  return {
@@ -85368,11 +85519,11 @@ async function technicalAeoRoutes(app, opts) {
85368
85519
  eq80(siteAuditSnapshots.projectId, project.id),
85369
85520
  eq80(runs.projectId, project.id),
85370
85521
  eq80(runs.kind, RunKinds["site-audit"]),
85371
- inArray31(runs.status, SURFACEABLE_STATUSES),
85522
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85372
85523
  notProbeRun()
85373
85524
  ];
85374
85525
  if (request.query.runId) targetFilters.push(eq80(siteAuditSnapshots.runId, request.query.runId));
85375
- 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();
85526
+ 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();
85376
85527
  if (!latest && request.query.runId) {
85377
85528
  throw notFound("Site audit run", request.query.runId);
85378
85529
  }
@@ -85387,7 +85538,7 @@ async function technicalAeoRoutes(app, opts) {
85387
85538
  const total = totalRow?.value ?? 0;
85388
85539
  const limit = parsePositiveInt(request.query.limit, 100, 500);
85389
85540
  const offset = parsePositiveInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER);
85390
- const orderBy = request.query.sort === "score-desc" ? desc35(siteAuditPages.overallScore) : request.query.sort === "url" ? asc14(siteAuditPages.url) : asc14(siteAuditPages.overallScore);
85541
+ const orderBy = request.query.sort === "score-desc" ? desc36(siteAuditPages.overallScore) : request.query.sort === "url" ? asc14(siteAuditPages.url) : asc14(siteAuditPages.overallScore);
85391
85542
  const rows = app.db.select().from(siteAuditPages).where(where).orderBy(orderBy).limit(limit).offset(offset).all();
85392
85543
  const pages = rows.map((row) => ({
85393
85544
  url: row.url,
@@ -85410,9 +85561,9 @@ async function technicalAeoRoutes(app, opts) {
85410
85561
  eq80(siteAuditSnapshots.projectId, project.id),
85411
85562
  eq80(runs.projectId, project.id),
85412
85563
  eq80(runs.kind, RunKinds["site-audit"]),
85413
- inArray31(runs.status, SURFACEABLE_STATUSES),
85564
+ inArray32(runs.status, SURFACEABLE_STATUSES),
85414
85565
  notProbeRun()
85415
- )).orderBy(desc35(siteAuditSnapshots.createdAt)).limit(limit).all();
85566
+ )).orderBy(desc36(siteAuditSnapshots.createdAt)).limit(limit).all();
85416
85567
  return { project: project.name, points: rows.reverse() };
85417
85568
  });
85418
85569
  app.get("/projects/:name/technical-aeo/crawl", async (request) => {
@@ -85718,8 +85869,8 @@ async function technicalAeoRoutes(app, opts) {
85718
85869
  eq80(siteCrawlEdges.internal, true),
85719
85870
  isNotNull8(siteCrawlEdges.targetNodeKey),
85720
85871
  or18(
85721
- inArray31(siteCrawlEdges.sourceNodeKey, frontier),
85722
- inArray31(siteCrawlEdges.targetNodeKey, frontier)
85872
+ inArray32(siteCrawlEdges.sourceNodeKey, frontier),
85873
+ inArray32(siteCrawlEdges.targetNodeKey, frontier)
85723
85874
  )
85724
85875
  )).orderBy(asc14(siteCrawlEdges.edgeKey)).limit(maxEdges + maxNodes + 1).all();
85725
85876
  if (candidates.length > maxEdges + maxNodes) queryTruncated = true;
@@ -85756,7 +85907,7 @@ async function technicalAeoRoutes(app, opts) {
85756
85907
  eq80(siteCrawlPages.projectId, scope.projectId),
85757
85908
  eq80(siteCrawlPages.runId, scope.runId),
85758
85909
  eq80(siteCrawlPages.attemptId, scope.attemptId),
85759
- inArray31(siteCrawlPages.nodeKey, nodeKeys)
85910
+ inArray32(siteCrawlPages.nodeKey, nodeKeys)
85760
85911
  )).all();
85761
85912
  const persistedNodeKeys = new Set(pageRows.map((row) => row.nodeKey));
85762
85913
  const outermostNodeKeys = pageRows.filter((row) => distances.get(row.nodeKey) === hops).map((row) => row.nodeKey);
@@ -85766,8 +85917,8 @@ async function technicalAeoRoutes(app, opts) {
85766
85917
  eq80(siteCrawlEdges.attemptId, scope.attemptId),
85767
85918
  eq80(siteCrawlEdges.internal, true),
85768
85919
  isNotNull8(siteCrawlEdges.targetNodeKey),
85769
- inArray31(siteCrawlEdges.sourceNodeKey, outermostNodeKeys),
85770
- inArray31(siteCrawlEdges.targetNodeKey, outermostNodeKeys)
85920
+ inArray32(siteCrawlEdges.sourceNodeKey, outermostNodeKeys),
85921
+ inArray32(siteCrawlEdges.targetNodeKey, outermostNodeKeys)
85771
85922
  )).limit(1).get();
85772
85923
  if (omittedOutermostEdge && !seenEdgeKeys.has(omittedOutermostEdge.edgeKey)) {
85773
85924
  omittedEdgeKeys.add(omittedOutermostEdge.edgeKey);
@@ -85870,7 +86021,7 @@ async function technicalAeoRoutes(app, opts) {
85870
86021
  eq80(siteCrawlEdges.followable, true),
85871
86022
  eq80(siteCrawlEdges.relation, "anchor"),
85872
86023
  isNotNull8(siteCrawlEdges.targetNodeKey),
85873
- inArray31(siteCrawlEdges.sourceNodeKey, frontier)
86024
+ inArray32(siteCrawlEdges.sourceNodeKey, frontier)
85874
86025
  )).orderBy(asc14(siteCrawlEdges.edgeKey)).limit(SITE_HEALTH_PATH_MAX_VISITED_NODES + 1).all();
85875
86026
  if (candidates.length > SITE_HEALTH_PATH_MAX_VISITED_NODES) truncated = true;
85876
86027
  const candidateTargetKeys = [...new Set(candidates.map((edge) => edge.targetNodeKey).filter((nodeKey) => nodeKey != null))];
@@ -85878,7 +86029,7 @@ async function technicalAeoRoutes(app, opts) {
85878
86029
  eq80(siteCrawlPages.projectId, scope.projectId),
85879
86030
  eq80(siteCrawlPages.runId, scope.runId),
85880
86031
  eq80(siteCrawlPages.attemptId, scope.attemptId),
85881
- inArray31(siteCrawlPages.nodeKey, candidateTargetKeys)
86032
+ inArray32(siteCrawlPages.nodeKey, candidateTargetKeys)
85882
86033
  )).all().map((row) => row.nodeKey));
85883
86034
  const next = /* @__PURE__ */ new Set();
85884
86035
  for (const edge of candidates.slice(0, SITE_HEALTH_PATH_MAX_VISITED_NODES)) {
@@ -85924,7 +86075,7 @@ async function technicalAeoRoutes(app, opts) {
85924
86075
  eq80(siteCrawlPages.projectId, scope.projectId),
85925
86076
  eq80(siteCrawlPages.runId, scope.runId),
85926
86077
  eq80(siteCrawlPages.attemptId, scope.attemptId),
85927
- inArray31(siteCrawlPages.nodeKey, pathKeys)
86078
+ inArray32(siteCrawlPages.nodeKey, pathKeys)
85928
86079
  )).all();
85929
86080
  const pageByKey = new Map(pathRows.map((row) => [row.nodeKey, row]));
85930
86081
  const pathDetection = templateDetectionOf(snapshot.templateDetection);
@@ -85960,7 +86111,7 @@ async function technicalAeoRoutes(app, opts) {
85960
86111
  eq80(siteCrawlSnapshots.complete, true),
85961
86112
  notProbeRun()
85962
86113
  ];
85963
- 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();
86114
+ 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();
85964
86115
  if (request.query.toRunId && !afterTarget) throw notFound("Site crawl run", request.query.toRunId);
85965
86116
  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(
85966
86117
  ...completeSnapshotFilters,
@@ -85971,7 +86122,7 @@ async function technicalAeoRoutes(app, opts) {
85971
86122
  lt13(siteCrawlSnapshots.runId, afterTarget.snapshot.runId)
85972
86123
  )
85973
86124
  )
85974
- )).orderBy(desc35(siteCrawlSnapshots.createdAt), desc35(siteCrawlSnapshots.runId)).limit(1).get() : void 0;
86125
+ )).orderBy(desc36(siteCrawlSnapshots.createdAt), desc36(siteCrawlSnapshots.runId)).limit(1).get() : void 0;
85975
86126
  if (request.query.fromRunId && !beforeTarget) throw notFound("Site crawl run", request.query.fromRunId);
85976
86127
  if (!afterTarget) {
85977
86128
  const latestCrawl = resolveCrawl(project.id);
@@ -86216,14 +86367,14 @@ async function technicalAeoRoutes(app, opts) {
86216
86367
  eq80(siteCrawlPages.projectId, scope.projectId),
86217
86368
  eq80(siteCrawlPages.runId, scope.runId),
86218
86369
  eq80(siteCrawlPages.attemptId, scope.attemptId),
86219
- inArray31(siteCrawlPages.nodeKey, pageKeys)
86370
+ inArray32(siteCrawlPages.nodeKey, pageKeys)
86220
86371
  )).all();
86221
86372
  const edgeRowsFor = (scope) => linkKeys.length === 0 ? [] : app.db.select().from(siteCrawlEdges).where(and67(
86222
86373
  eq80(siteCrawlEdges.projectId, scope.projectId),
86223
86374
  eq80(siteCrawlEdges.runId, scope.runId),
86224
86375
  eq80(siteCrawlEdges.attemptId, scope.attemptId),
86225
86376
  eq80(siteCrawlEdges.internal, true),
86226
- inArray31(siteCrawlEdges.edgeKey, linkKeys)
86377
+ inArray32(siteCrawlEdges.edgeKey, linkKeys)
86227
86378
  )).all();
86228
86379
  const beforePages = new Map(pageRowsFor(beforeScope).map((row) => [row.nodeKey, mapCrawlPage(row)]));
86229
86380
  const afterPages = new Map(pageRowsFor(afterScope).map((row) => [row.nodeKey, mapCrawlPage(row)]));
@@ -86361,7 +86512,7 @@ async function technicalAeoRoutes(app, opts) {
86361
86512
  const healthState = parseSiteHealthState(request.query.healthState);
86362
86513
  const limit = parseBoundedLimit(request.query.limit, 100, 200);
86363
86514
  const offset = decodeCursor(request.query.cursor);
86364
- 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)];
86515
+ 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)];
86365
86516
  let healthStateFilter = null;
86366
86517
  if (healthState) {
86367
86518
  const legacyRow = app.db.select({ id: siteCrawlPages.id }).from(siteCrawlPages).where(and67(
@@ -86674,15 +86825,15 @@ async function technicalAeoRoutes(app, opts) {
86674
86825
  eq80(runs.projectId, project.id),
86675
86826
  eq80(runs.kind, RunKinds["site-audit"]),
86676
86827
  notProbeRun()
86677
- )).orderBy(desc35(runs.createdAt), desc35(runs.id)).limit(limit).all();
86828
+ )).orderBy(desc36(runs.createdAt), desc36(runs.id)).limit(limit).all();
86678
86829
  const runIds = rows.map((row) => row.runId);
86679
86830
  const crawlRunIds = new Set(runIds.length === 0 ? [] : app.db.select({ runId: siteCrawlSnapshots.runId }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(
86680
86831
  eq80(siteCrawlSnapshots.projectId, project.id),
86681
86832
  eq80(runs.projectId, project.id),
86682
86833
  eq80(runs.kind, RunKinds["site-audit"]),
86683
- inArray31(runs.status, SURFACEABLE_STATUSES),
86834
+ inArray32(runs.status, SURFACEABLE_STATUSES),
86684
86835
  notProbeRun(),
86685
- inArray31(siteCrawlSnapshots.runId, runIds)
86836
+ inArray32(siteCrawlSnapshots.runId, runIds)
86686
86837
  )).all().map((row) => row.runId));
86687
86838
  return {
86688
86839
  project: project.name,
@@ -86705,7 +86856,7 @@ async function technicalAeoRoutes(app, opts) {
86705
86856
  const attempt = app.db.select().from(siteCrawlAttempts).where(and67(
86706
86857
  eq80(siteCrawlAttempts.projectId, project.id),
86707
86858
  eq80(siteCrawlAttempts.runId, run.id)
86708
- )).orderBy(desc35(siteCrawlAttempts.attemptNumber), desc35(siteCrawlAttempts.updatedAt)).limit(1).get();
86859
+ )).orderBy(desc36(siteCrawlAttempts.attemptNumber), desc36(siteCrawlAttempts.updatedAt)).limit(1).get();
86709
86860
  const persistedLayout = attempt ? app.db.select().from(siteCrawlGraphLayouts).where(and67(
86710
86861
  eq80(siteCrawlGraphLayouts.projectId, project.id),
86711
86862
  eq80(siteCrawlGraphLayouts.runId, run.id),
@@ -86752,7 +86903,7 @@ async function technicalAeoRoutes(app, opts) {
86752
86903
  const attempt = tx.select().from(siteCrawlAttempts).where(and67(
86753
86904
  eq80(siteCrawlAttempts.projectId, project.id),
86754
86905
  eq80(siteCrawlAttempts.runId, run.id)
86755
- )).orderBy(desc35(siteCrawlAttempts.attemptNumber), desc35(siteCrawlAttempts.updatedAt)).limit(1).get();
86906
+ )).orderBy(desc36(siteCrawlAttempts.attemptNumber), desc36(siteCrawlAttempts.updatedAt)).limit(1).get();
86756
86907
  const state = run.status === RunStatuses.queued ? "waiting" : run.status === RunStatuses.running ? "collecting" : "terminal";
86757
86908
  const base = {
86758
86909
  project: project.name,
@@ -86822,7 +86973,7 @@ async function technicalAeoRoutes(app, opts) {
86822
86973
  )).where(and67(
86823
86974
  eq80(runs.projectId, project.id),
86824
86975
  eq80(runs.kind, RunKinds["site-audit"]),
86825
- inArray31(runs.status, [RunStatuses.queued, RunStatuses.running])
86976
+ inArray32(runs.status, [RunStatuses.queued, RunStatuses.running])
86826
86977
  )).get();
86827
86978
  if (existing) {
86828
86979
  if (existing.identityKey === identityKey) {
@@ -86876,7 +87027,7 @@ async function technicalAeoRoutes(app, opts) {
86876
87027
  // ../api-routes/src/research.ts
86877
87028
  import crypto50 from "crypto";
86878
87029
  import { z as z5 } from "zod";
86879
- 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";
87030
+ 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";
86880
87031
  var sameLocation = (a, b) => a.label === b.label && a.city === b.city && a.region === b.region && a.country === b.country && a.timezone === b.timezone;
86881
87032
  var BATCH_RECEIPT_PREFIX = "__canonry_research_batch__:";
86882
87033
  async function researchRoutes(app, opts) {
@@ -87047,7 +87198,7 @@ async function researchRoutes(app, opts) {
87047
87198
  const rows = app.db.select().from(researchRuns).where(and68(
87048
87199
  eq81(researchRuns.projectId, project.id),
87049
87200
  cursor ? or19(lt14(researchRuns.createdAt, cursor.createdAt), and68(eq81(researchRuns.createdAt, cursor.createdAt), lt14(researchRuns.id, cursor.id))) : void 0
87050
- )).orderBy(desc36(researchRuns.createdAt), desc36(researchRuns.id)).limit(limit + 1).all();
87201
+ )).orderBy(desc37(researchRuns.createdAt), desc37(researchRuns.id)).limit(limit + 1).all();
87051
87202
  const runs2 = rows.slice(0, limit).map(serializeRun);
87052
87203
  const last = runs2.at(-1);
87053
87204
  const nextCursor = rows.length > limit && last ? Buffer.from(JSON.stringify({ projectId: project.id, createdAt: last.createdAt, id: last.id })).toString("base64url") : null;
@@ -87228,7 +87379,7 @@ function utcDayBounds(now) {
87228
87379
  }
87229
87380
 
87230
87381
  // ../api-routes/src/snapshot-competitor-refresh.ts
87231
- import { and as and69, eq as eq82, inArray as inArray32 } from "drizzle-orm";
87382
+ import { and as and69, eq as eq82, inArray as inArray33 } from "drizzle-orm";
87232
87383
  var SNAPSHOT_BATCH_SIZE = 500;
87233
87384
  function backfillProjectAnswerMentions(db, projectId, opts) {
87234
87385
  const isDryRun = opts?.dryRun === true;
@@ -87272,7 +87423,7 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
87272
87423
  competitorOverlap: querySnapshots.competitorOverlap,
87273
87424
  recommendedCompetitors: querySnapshots.recommendedCompetitors,
87274
87425
  rawResponse: querySnapshots.rawResponse
87275
- }).from(querySnapshots).where(inArray32(querySnapshots.runId, batchRunIds)).all();
87426
+ }).from(querySnapshots).where(inArray33(querySnapshots.runId, batchRunIds)).all();
87276
87427
  const pendingUpdates = [];
87277
87428
  for (const snapshot of snapshotRows) {
87278
87429
  if (competitorFieldsOnly && snapshot.answerText == null) continue;
@@ -88328,7 +88479,7 @@ var IntelligenceService = class {
88328
88479
  this.db.select({ one: sql31`1` }).from(querySnapshots).where(eq84(querySnapshots.runId, runs.id))
88329
88480
  )
88330
88481
  )
88331
- ).orderBy(desc37(runs.finishedAt), desc37(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
88482
+ ).orderBy(desc38(runs.finishedAt), desc38(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
88332
88483
  const trackedCompetitors = this.loadTrackedCompetitors(projectId);
88333
88484
  const currentRun = this.buildRunData(
88334
88485
  runId,
@@ -88447,10 +88598,10 @@ var IntelligenceService = class {
88447
88598
  buildGbpLocationSignals(projectId, locationName, displayName, fallbackDate) {
88448
88599
  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();
88449
88600
  const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and71(eq84(gbpPlaceActions.projectId, projectId), eq84(gbpPlaceActions.locationName, locationName))).all();
88450
- 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();
88601
+ 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();
88451
88602
  const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and71(eq84(gbpLocations.projectId, projectId), eq84(gbpLocations.locationName, locationName))).get();
88452
88603
  const descriptionMissing = !(ownerRow?.description ?? "").trim();
88453
- 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();
88604
+ 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();
88454
88605
  const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
88455
88606
  const summary3 = buildGbpSummary({
88456
88607
  locationName,
@@ -88657,7 +88808,7 @@ var IntelligenceService = class {
88657
88808
  let wouldDeleteTotal = 0;
88658
88809
  const existingByRunId = /* @__PURE__ */ new Map();
88659
88810
  if (isDryRun && targetRuns.length > 0) {
88660
- const rows = this.db.select({ runId: insights.runId }).from(insights).where(inArray33(insights.runId, targetRuns.map((r) => r.id))).all();
88811
+ const rows = this.db.select({ runId: insights.runId }).from(insights).where(inArray34(insights.runId, targetRuns.map((r) => r.id))).all();
88661
88812
  for (const r of rows) {
88662
88813
  if (r.runId == null) continue;
88663
88814
  existingByRunId.set(r.runId, (existingByRunId.get(r.runId) ?? 0) + 1);
@@ -88712,7 +88863,7 @@ var IntelligenceService = class {
88712
88863
  */
88713
88864
  runIdsWithSnapshots(runIds) {
88714
88865
  if (runIds.length === 0) return /* @__PURE__ */ new Set();
88715
- const rows = this.db.select({ runId: querySnapshots.runId }).from(querySnapshots).where(inArray33(querySnapshots.runId, [...runIds])).groupBy(querySnapshots.runId).all();
88866
+ const rows = this.db.select({ runId: querySnapshots.runId }).from(querySnapshots).where(inArray34(querySnapshots.runId, [...runIds])).groupBy(querySnapshots.runId).all();
88716
88867
  return new Set(rows.map((r) => r.runId));
88717
88868
  }
88718
88869
  /**
@@ -88857,7 +89008,7 @@ var IntelligenceService = class {
88857
89008
  // Defensive — see top of file.
88858
89009
  ne15(runs.trigger, RunTriggers.probe)
88859
89010
  )
88860
- ).orderBy(desc37(runs.createdAt), desc37(runs.id)).limit((RECURRENCE_LOOKBACK_RUNS + 1) * ROWS_PER_GROUP_BUDGET).all();
89011
+ ).orderBy(desc38(runs.createdAt), desc38(runs.id)).limit((RECURRENCE_LOOKBACK_RUNS + 1) * ROWS_PER_GROUP_BUDGET).all();
88861
89012
  const recentGroups = groupRunsByCreatedAt(recentRunRows);
88862
89013
  const recentRunIds = [];
88863
89014
  const recentRunIdToCreatedAt = /* @__PURE__ */ new Map();
@@ -88873,7 +89024,7 @@ var IntelligenceService = class {
88873
89024
  const haveHistory = recentRunIds.length > 0;
88874
89025
  const priorRegressionsByPair = /* @__PURE__ */ new Map();
88875
89026
  if (haveHistory) {
88876
- 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();
89027
+ 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();
88877
89028
  const regressionGroups = /* @__PURE__ */ new Map();
88878
89029
  for (const row of priorRows) {
88879
89030
  if (!row.runId) continue;