@canonry/canonry 4.152.0 → 4.154.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.
- package/assets/assets/{AuditHistoryPanel-DK52bxkQ.js → AuditHistoryPanel-WWT1n8jp.js} +1 -1
- package/assets/assets/{BacklinksPage-DYApSbsM.js → BacklinksPage-DIjUnsVL.js} +1 -1
- package/assets/assets/{HistoryPage-CksKbEHx.js → HistoryPage-CrIBhGuW.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-Ds5A7BiY.js → MeasurementPropertyPage-uN4BWigS.js} +1 -1
- package/assets/assets/ProjectPage-BR5ECwUP.js +12 -0
- package/assets/assets/{RunRow-C0oX3797.js → RunRow-OE5tiuih.js} +1 -1
- package/assets/assets/{RunsPage-0qr4V3pn.js → RunsPage-C6xBmjps.js} +1 -1
- package/assets/assets/{SettingsPage-BLMy_cfR.js → SettingsPage-CUjjr8U0.js} +1 -1
- package/assets/assets/{TrafficPage-CZj9XGfC.js → TrafficPage-DrEfsHiE.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-BfQAuIQM.js → TrafficSourceDetailPage-B3DX5BEk.js} +1 -1
- package/assets/assets/{arrow-left-DdovB6GZ.js → arrow-left-CLmqvCqU.js} +1 -1
- package/assets/assets/{extract-error-message-yI0U8t_A.js → extract-error-message-BEBd1a5v.js} +1 -1
- package/assets/assets/{index-DP74nMja.js → index-CsM-Xxia.js} +68 -68
- package/assets/assets/{index-CiidhUL0.css → index-DyL54s8x.css} +1 -1
- package/assets/assets/{refresh-cw-SR8k0mBu.js → refresh-cw-DYSS2Wd-.js} +1 -1
- package/assets/assets/{trash-2-DQF9iFSX.js → trash-2-VoiF_ckU.js} +1 -1
- package/assets/assets/v2-overview-adapter-COMP5UGt.js +1 -0
- package/assets/index.html +2 -2
- package/dist/{chunk-TS3AHKZG.js → chunk-ANSQ6JNO.js} +1 -1
- package/dist/{chunk-JWTFZG7Q.js → chunk-IFZS2TXV.js} +154 -83
- package/dist/{chunk-BUAVO37B.js → chunk-NNW7TJUZ.js} +15 -0
- package/dist/{chunk-G7P5CJJS.js → chunk-X5I7CAXH.js} +172 -77
- package/dist/cli.js +4 -4
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-KBFVQOPO.js → intelligence-service-B5AETQ5N.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +7 -7
- package/assets/assets/ProjectPage-LzCmnrO2.js +0 -12
- package/assets/assets/v2-overview-adapter-Dz0UmhmS.js +0 -1
|
@@ -521,7 +521,7 @@ import {
|
|
|
521
521
|
wordpressSchemaDeployResultDtoSchema,
|
|
522
522
|
wordpressSchemaStatusResultDtoSchema,
|
|
523
523
|
wordpressStatusDtoSchema
|
|
524
|
-
} from "./chunk-
|
|
524
|
+
} from "./chunk-NNW7TJUZ.js";
|
|
525
525
|
|
|
526
526
|
// src/intelligence-service.ts
|
|
527
527
|
import { eq as eq57, desc as desc26, asc as asc11, and as and45, ne as ne7, or as or11, inArray as inArray19, gte as gte13, lte as lte10 } from "drizzle-orm";
|
|
@@ -15721,6 +15721,31 @@ function validatedCursor(query, activePlanVersionId) {
|
|
|
15721
15721
|
}
|
|
15722
15722
|
return cursor;
|
|
15723
15723
|
}
|
|
15724
|
+
function measurementOutcomeCounts(rows) {
|
|
15725
|
+
const counts2 = {
|
|
15726
|
+
bothSignals: 0,
|
|
15727
|
+
mentionedOnly: 0,
|
|
15728
|
+
citedOnly: 0,
|
|
15729
|
+
neither: 0,
|
|
15730
|
+
notMeasured: 0,
|
|
15731
|
+
total: rows.length
|
|
15732
|
+
};
|
|
15733
|
+
for (const row of rows) {
|
|
15734
|
+
const mention = row.mentionCoverage;
|
|
15735
|
+
const citation = row.citationCoverage;
|
|
15736
|
+
if (mention.state !== "available" || citation.state !== "available") {
|
|
15737
|
+
counts2.notMeasured += 1;
|
|
15738
|
+
continue;
|
|
15739
|
+
}
|
|
15740
|
+
const mentioned = (mention.numerator ?? mention.value) > 0;
|
|
15741
|
+
const cited = (citation.numerator ?? citation.value) > 0;
|
|
15742
|
+
if (mentioned && cited) counts2.bothSignals += 1;
|
|
15743
|
+
else if (mentioned) counts2.mentionedOnly += 1;
|
|
15744
|
+
else if (cited) counts2.citedOnly += 1;
|
|
15745
|
+
else counts2.neither += 1;
|
|
15746
|
+
}
|
|
15747
|
+
return counts2;
|
|
15748
|
+
}
|
|
15724
15749
|
function pageOf(rows, query, displayedRunId, activePlanVersionId, evidenceFingerprint) {
|
|
15725
15750
|
const sort = query.sort ?? MEASUREMENT_OVERVIEW_DEFAULT_SORT;
|
|
15726
15751
|
const ordered = [...rows].sort((left, right) => compareRows(left, right, sort));
|
|
@@ -15738,16 +15763,19 @@ function pageOf(rows, query, displayedRunId, activePlanVersionId, evidenceFinger
|
|
|
15738
15763
|
const items = ordered.slice(offset, offset + limit);
|
|
15739
15764
|
const last = items.at(-1);
|
|
15740
15765
|
return {
|
|
15741
|
-
|
|
15742
|
-
|
|
15743
|
-
last
|
|
15744
|
-
|
|
15745
|
-
|
|
15746
|
-
|
|
15747
|
-
|
|
15748
|
-
|
|
15749
|
-
|
|
15750
|
-
|
|
15766
|
+
page: {
|
|
15767
|
+
items,
|
|
15768
|
+
nextCursor: last === void 0 || ordered.at(offset + limit) === void 0 ? null : cursorOf(
|
|
15769
|
+
last,
|
|
15770
|
+
sort,
|
|
15771
|
+
displayedRunId,
|
|
15772
|
+
overviewFilterFingerprint(query),
|
|
15773
|
+
activePlanVersionId,
|
|
15774
|
+
evidenceFingerprint
|
|
15775
|
+
),
|
|
15776
|
+
totalEstimate: ordered.length
|
|
15777
|
+
},
|
|
15778
|
+
outcomes: measurementOutcomeCounts(ordered)
|
|
15751
15779
|
};
|
|
15752
15780
|
}
|
|
15753
15781
|
function runRevisionMismatch(runId, runRevision, activeRevision) {
|
|
@@ -15879,7 +15907,7 @@ function runProgress(db, displayed, plan) {
|
|
|
15879
15907
|
}
|
|
15880
15908
|
function planV1Overview(db, projectId, active, query, scope) {
|
|
15881
15909
|
const displayed = selectDisplayedRun(db, projectId, active, query);
|
|
15882
|
-
const page = pageOf(
|
|
15910
|
+
const { page, outcomes } = pageOf(
|
|
15883
15911
|
propertyLabels(active.plan, scope).filter((row) => matchesSearch(row, query.search)).map((row) => ({
|
|
15884
15912
|
...row,
|
|
15885
15913
|
mentionCoverage: unavailable2("plan_v1"),
|
|
@@ -15913,6 +15941,7 @@ function planV1Overview(db, projectId, active, query, scope) {
|
|
|
15913
15941
|
sov: unavailable2("plan_v1")
|
|
15914
15942
|
},
|
|
15915
15943
|
properties: page,
|
|
15944
|
+
outcomes,
|
|
15916
15945
|
flags: { total: 0 }
|
|
15917
15946
|
};
|
|
15918
15947
|
}
|
|
@@ -15922,7 +15951,7 @@ function planV2Overview(db, projectId, active, plan, query, scope, cache) {
|
|
|
15922
15951
|
const current = latestMeasurementRun(db, projectId, active.version.id, CURRENT_RUN_STATUSES);
|
|
15923
15952
|
const currentDto = current ? { currentRunId: current.id } : {};
|
|
15924
15953
|
if (!displayed) {
|
|
15925
|
-
const page2 = pageOf(
|
|
15954
|
+
const { page: page2, outcomes: outcomes2 } = pageOf(
|
|
15926
15955
|
propertyLabels(plan, scope).filter((row) => matchesSearch(row, query.search)).map((row) => ({
|
|
15927
15956
|
...row,
|
|
15928
15957
|
mentionCoverage: unavailable2("no_completed_run"),
|
|
@@ -15954,6 +15983,7 @@ function planV2Overview(db, projectId, active, plan, query, scope, cache) {
|
|
|
15954
15983
|
sov: unavailable2("no_completed_run")
|
|
15955
15984
|
},
|
|
15956
15985
|
properties: page2,
|
|
15986
|
+
outcomes: outcomes2,
|
|
15957
15987
|
flags: { total: 0 }
|
|
15958
15988
|
};
|
|
15959
15989
|
}
|
|
@@ -15982,7 +16012,7 @@ function planV2Overview(db, projectId, active, plan, query, scope, cache) {
|
|
|
15982
16012
|
const measured = new Map(
|
|
15983
16013
|
overview.properties.map((row) => [row.targetId, row])
|
|
15984
16014
|
);
|
|
15985
|
-
const page = pageOf(
|
|
16015
|
+
const { page, outcomes } = pageOf(
|
|
15986
16016
|
propertyLabels(plan, scope).filter((row) => matchesSearch(row, query.search)).map((row) => {
|
|
15987
16017
|
const property = measured.get(row.targetKey);
|
|
15988
16018
|
return {
|
|
@@ -16036,6 +16066,7 @@ function planV2Overview(db, projectId, active, plan, query, scope, cache) {
|
|
|
16036
16066
|
sov: brandPresence
|
|
16037
16067
|
},
|
|
16038
16068
|
properties: page,
|
|
16069
|
+
outcomes,
|
|
16039
16070
|
flags: { total: overview.flags },
|
|
16040
16071
|
...namedShareOfVoice === void 0 ? {} : { namedShareOfVoice }
|
|
16041
16072
|
};
|
|
@@ -35470,8 +35501,9 @@ function isSitemapOwnedByProperty(sitemapUrl, propertyId, canonicalDomain) {
|
|
|
35470
35501
|
function signState(payload, secret) {
|
|
35471
35502
|
return crypto29.createHmac("sha256", secret).update(payload).digest("hex");
|
|
35472
35503
|
}
|
|
35504
|
+
var OAUTH_STATE_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
35473
35505
|
function buildSignedState(data, secret) {
|
|
35474
|
-
const payload = JSON.stringify(data);
|
|
35506
|
+
const payload = JSON.stringify({ ...data, issuedAt: Date.now() });
|
|
35475
35507
|
const sig = signState(payload, secret);
|
|
35476
35508
|
return Buffer.from(JSON.stringify({ payload, sig })).toString("base64url");
|
|
35477
35509
|
}
|
|
@@ -35480,7 +35512,10 @@ function verifySignedState(encoded, secret) {
|
|
|
35480
35512
|
const { payload, sig } = JSON.parse(Buffer.from(encoded, "base64url").toString());
|
|
35481
35513
|
const expected = signState(payload, secret);
|
|
35482
35514
|
if (!crypto29.timingSafeEqual(Buffer.from(sig, "hex"), Buffer.from(expected, "hex"))) return null;
|
|
35483
|
-
|
|
35515
|
+
const parsed = JSON.parse(payload);
|
|
35516
|
+
const issuedAt = typeof parsed.issuedAt === "number" ? parsed.issuedAt : null;
|
|
35517
|
+
if (issuedAt === null || Date.now() - issuedAt > OAUTH_STATE_MAX_AGE_MS) return null;
|
|
35518
|
+
return parsed;
|
|
35484
35519
|
} catch {
|
|
35485
35520
|
return null;
|
|
35486
35521
|
}
|
|
@@ -41766,9 +41801,12 @@ async function adsRoutes(app, opts) {
|
|
|
41766
41801
|
}
|
|
41767
41802
|
|
|
41768
41803
|
// ../api-routes/src/bing.ts
|
|
41769
|
-
import
|
|
41804
|
+
import crypto34 from "crypto";
|
|
41770
41805
|
import { eq as eq42, and as and33, desc as desc19 } from "drizzle-orm";
|
|
41771
41806
|
|
|
41807
|
+
// ../integration-bing/src/bing-client.ts
|
|
41808
|
+
import crypto33 from "crypto";
|
|
41809
|
+
|
|
41772
41810
|
// ../integration-bing/src/constants.ts
|
|
41773
41811
|
var BING_WMT_API_BASE = "https://ssl.bing.com/webmaster/api.svc/json";
|
|
41774
41812
|
var BING_SUBMIT_URL_BATCH_LIMIT = 500;
|
|
@@ -41777,6 +41815,7 @@ var BING_REQUEST_TIMEOUT_MS = 3e4;
|
|
|
41777
41815
|
var BING_MAX_RETRIES = 4;
|
|
41778
41816
|
var BING_RETRY_BASE_DELAY_MS = 2e3;
|
|
41779
41817
|
var BING_RETRY_MAX_DELAY_MS = 3e4;
|
|
41818
|
+
var BING_THROTTLE_COOLDOWN_MS = 10 * 60 * 1e3;
|
|
41780
41819
|
|
|
41781
41820
|
// ../integration-bing/src/types.ts
|
|
41782
41821
|
var BING_THROTTLE_ERROR_CODES = /* @__PURE__ */ new Set([4, 5]);
|
|
@@ -41916,26 +41955,58 @@ async function bingFetchOnce(apiKey, endpoint, opts) {
|
|
|
41916
41955
|
throw new BingApiError("Bing API returned invalid JSON", 502);
|
|
41917
41956
|
}
|
|
41918
41957
|
}
|
|
41958
|
+
var throttleCooldownUntil = /* @__PURE__ */ new Map();
|
|
41959
|
+
var cooldownNow = () => Date.now();
|
|
41960
|
+
function cooldownKey(apiKey) {
|
|
41961
|
+
return crypto33.createHash("sha256").update(apiKey).digest("hex").slice(0, 12);
|
|
41962
|
+
}
|
|
41963
|
+
function throttleCooldownRemainingMs(apiKey) {
|
|
41964
|
+
const until = throttleCooldownUntil.get(cooldownKey(apiKey));
|
|
41965
|
+
if (until == null) return 0;
|
|
41966
|
+
const remaining = until - cooldownNow();
|
|
41967
|
+
if (remaining <= 0) {
|
|
41968
|
+
throttleCooldownUntil.delete(cooldownKey(apiKey));
|
|
41969
|
+
return 0;
|
|
41970
|
+
}
|
|
41971
|
+
return remaining;
|
|
41972
|
+
}
|
|
41973
|
+
function openThrottleCooldown(apiKey) {
|
|
41974
|
+
throttleCooldownUntil.set(cooldownKey(apiKey), cooldownNow() + BING_THROTTLE_COOLDOWN_MS);
|
|
41975
|
+
bingClientLog("error", "http.cooldown-open", { cooldownMs: BING_THROTTLE_COOLDOWN_MS });
|
|
41976
|
+
}
|
|
41919
41977
|
async function bingFetch(apiKey, endpoint, opts) {
|
|
41920
41978
|
const isIdempotent = (opts?.method ?? "GET") === "GET";
|
|
41921
|
-
|
|
41922
|
-
|
|
41923
|
-
|
|
41924
|
-
|
|
41925
|
-
|
|
41926
|
-
|
|
41927
|
-
|
|
41928
|
-
|
|
41929
|
-
|
|
41930
|
-
|
|
41931
|
-
|
|
41932
|
-
|
|
41933
|
-
|
|
41934
|
-
|
|
41935
|
-
|
|
41936
|
-
|
|
41937
|
-
|
|
41938
|
-
|
|
41979
|
+
const cooling = throttleCooldownRemainingMs(apiKey);
|
|
41980
|
+
if (cooling > 0) {
|
|
41981
|
+
bingClientLog("warn", "http.cooldown-skip", { endpoint, remainingMs: cooling });
|
|
41982
|
+
throw new BingApiError(
|
|
41983
|
+
`Bing API key is in a throttle cooldown for another ${Math.ceil(cooling / 1e3)}s; the account was still throttled after a full retry budget, so this call was not attempted.`,
|
|
41984
|
+
429
|
|
41985
|
+
);
|
|
41986
|
+
}
|
|
41987
|
+
try {
|
|
41988
|
+
return await withRetry(() => bingFetchOnce(apiKey, endpoint, opts), {
|
|
41989
|
+
maxRetries: BING_MAX_RETRIES,
|
|
41990
|
+
baseDelayMs: BING_RETRY_BASE_DELAY_MS,
|
|
41991
|
+
maxDelayMs: BING_RETRY_MAX_DELAY_MS,
|
|
41992
|
+
isRetryable: (err) => {
|
|
41993
|
+
if (err instanceof BingApiError && err.isThrottle) return true;
|
|
41994
|
+
return isIdempotent && isRetryableHttpError(err);
|
|
41995
|
+
},
|
|
41996
|
+
computeDelayMs: (_attempt, err, defaultMs) => retryAfterDelayMs(err) ?? defaultMs,
|
|
41997
|
+
onRetry: ({ attempt, err, delayMs }) => {
|
|
41998
|
+
bingClientLog("warn", "http.retry", {
|
|
41999
|
+
endpoint,
|
|
42000
|
+
attempt,
|
|
42001
|
+
delayMs: Math.round(delayMs),
|
|
42002
|
+
throttled: err instanceof BingApiError ? err.isThrottle : false
|
|
42003
|
+
});
|
|
42004
|
+
}
|
|
42005
|
+
});
|
|
42006
|
+
} catch (err) {
|
|
42007
|
+
if (err instanceof BingApiError && err.isThrottle) openThrottleCooldown(apiKey);
|
|
42008
|
+
throw err;
|
|
42009
|
+
}
|
|
41939
42010
|
}
|
|
41940
42011
|
async function getSites(apiKey) {
|
|
41941
42012
|
validateApiKey(apiKey);
|
|
@@ -42206,7 +42277,7 @@ async function bingRoutes(app, opts) {
|
|
|
42206
42277
|
const snapshotDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
42207
42278
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
42208
42279
|
app.db.insert(bingCoverageSnapshots).values({
|
|
42209
|
-
id:
|
|
42280
|
+
id: crypto34.randomUUID(),
|
|
42210
42281
|
projectId: project.id,
|
|
42211
42282
|
syncRunId: snapshotRunId,
|
|
42212
42283
|
date: snapshotDate,
|
|
@@ -42277,7 +42348,7 @@ async function bingRoutes(app, opts) {
|
|
|
42277
42348
|
throw validationError("url is required");
|
|
42278
42349
|
}
|
|
42279
42350
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
42280
|
-
const runId =
|
|
42351
|
+
const runId = crypto34.randomUUID();
|
|
42281
42352
|
app.db.insert(runs).values({
|
|
42282
42353
|
id: runId,
|
|
42283
42354
|
projectId: project.id,
|
|
@@ -42298,7 +42369,7 @@ async function bingRoutes(app, opts) {
|
|
|
42298
42369
|
discoveryDate: result.DiscoveryDate ?? null
|
|
42299
42370
|
});
|
|
42300
42371
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
42301
|
-
const id =
|
|
42372
|
+
const id = crypto34.randomUUID();
|
|
42302
42373
|
const httpCode = result.HttpStatus ?? result.HttpCode ?? null;
|
|
42303
42374
|
const lastCrawledDate = parseBingDate(result.LastCrawledDate);
|
|
42304
42375
|
const inIndexDate = parseBingDate(result.InIndexDate);
|
|
@@ -42368,7 +42439,7 @@ async function bingRoutes(app, opts) {
|
|
|
42368
42439
|
throw validationError('No Bing site configured. Run "canonry bing set-site <project> <url>" first.');
|
|
42369
42440
|
}
|
|
42370
42441
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
42371
|
-
const runId =
|
|
42442
|
+
const runId = crypto34.randomUUID();
|
|
42372
42443
|
app.db.insert(runs).values({
|
|
42373
42444
|
id: runId,
|
|
42374
42445
|
projectId: project.id,
|
|
@@ -42653,7 +42724,7 @@ async function cdpRoutes(app, opts) {
|
|
|
42653
42724
|
}
|
|
42654
42725
|
|
|
42655
42726
|
// ../api-routes/src/ga.ts
|
|
42656
|
-
import
|
|
42727
|
+
import crypto35 from "crypto";
|
|
42657
42728
|
import { eq as eq44, desc as desc20, and as and35, sql as sql16 } from "drizzle-orm";
|
|
42658
42729
|
|
|
42659
42730
|
// ../api-routes/src/ga-session-history.ts
|
|
@@ -42855,7 +42926,7 @@ function persistAcquisitionMeasurement(db, input) {
|
|
|
42855
42926
|
)).run();
|
|
42856
42927
|
for (const row of input.report.rows) {
|
|
42857
42928
|
tx.insert(gaAcquisitionDaily).values({
|
|
42858
|
-
id:
|
|
42929
|
+
id: crypto35.randomUUID(),
|
|
42859
42930
|
projectId: input.projectId,
|
|
42860
42931
|
date: row.date,
|
|
42861
42932
|
channelGroup: row.channelGroup,
|
|
@@ -42897,7 +42968,7 @@ function persistLeadMeasurement(db, input) {
|
|
|
42897
42968
|
)).run();
|
|
42898
42969
|
for (const row of input.report.rows) {
|
|
42899
42970
|
tx.insert(gaLeadEventsDaily).values({
|
|
42900
|
-
id:
|
|
42971
|
+
id: crypto35.randomUUID(),
|
|
42901
42972
|
projectId: input.projectId,
|
|
42902
42973
|
date: row.date,
|
|
42903
42974
|
eventName: row.eventName,
|
|
@@ -43177,7 +43248,7 @@ async function ga4Routes(app, opts) {
|
|
|
43177
43248
|
const leadDays = measurementState?.leadSyncedAt != null ? Math.min(Math.max(1, days), 90) : 90;
|
|
43178
43249
|
const leadEventNames = project.measurement.leadEventNames;
|
|
43179
43250
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43180
|
-
const runId =
|
|
43251
|
+
const runId = crypto35.randomUUID();
|
|
43181
43252
|
app.db.insert(runs).values({
|
|
43182
43253
|
id: runId,
|
|
43183
43254
|
projectId: project.id,
|
|
@@ -43231,7 +43302,7 @@ async function ga4Routes(app, opts) {
|
|
|
43231
43302
|
).run();
|
|
43232
43303
|
for (const row of rows) {
|
|
43233
43304
|
tx.insert(gaTrafficSnapshots).values({
|
|
43234
|
-
id:
|
|
43305
|
+
id: crypto35.randomUUID(),
|
|
43235
43306
|
projectId: project.id,
|
|
43236
43307
|
date: row.date,
|
|
43237
43308
|
landingPage: row.landingPage,
|
|
@@ -43254,7 +43325,7 @@ async function ga4Routes(app, opts) {
|
|
|
43254
43325
|
).run();
|
|
43255
43326
|
for (const row of dailyTotals) {
|
|
43256
43327
|
tx.insert(gaDailyTotals).values({
|
|
43257
|
-
id:
|
|
43328
|
+
id: crypto35.randomUUID(),
|
|
43258
43329
|
projectId: project.id,
|
|
43259
43330
|
date: row.date,
|
|
43260
43331
|
sessions: row.sessions,
|
|
@@ -43280,7 +43351,7 @@ async function ga4Routes(app, opts) {
|
|
|
43280
43351
|
).run();
|
|
43281
43352
|
for (const row of aiReferrals) {
|
|
43282
43353
|
tx.insert(gaAiReferrals).values({
|
|
43283
|
-
id:
|
|
43354
|
+
id: crypto35.randomUUID(),
|
|
43284
43355
|
projectId: project.id,
|
|
43285
43356
|
date: row.date,
|
|
43286
43357
|
source: row.source,
|
|
@@ -43312,7 +43383,7 @@ async function ga4Routes(app, opts) {
|
|
|
43312
43383
|
).run();
|
|
43313
43384
|
for (const row of socialReferrals) {
|
|
43314
43385
|
tx.insert(gaSocialReferrals).values({
|
|
43315
|
-
id:
|
|
43386
|
+
id: crypto35.randomUUID(),
|
|
43316
43387
|
projectId: project.id,
|
|
43317
43388
|
date: row.date,
|
|
43318
43389
|
source: row.source,
|
|
@@ -43328,7 +43399,7 @@ async function ga4Routes(app, opts) {
|
|
|
43328
43399
|
if (syncSummary) {
|
|
43329
43400
|
tx.delete(gaTrafficSummaries).where(eq44(gaTrafficSummaries.projectId, project.id)).run();
|
|
43330
43401
|
tx.insert(gaTrafficSummaries).values({
|
|
43331
|
-
id:
|
|
43402
|
+
id: crypto35.randomUUID(),
|
|
43332
43403
|
projectId: project.id,
|
|
43333
43404
|
periodStart: summary.periodStart,
|
|
43334
43405
|
periodEnd: summary.periodEnd,
|
|
@@ -43341,7 +43412,7 @@ async function ga4Routes(app, opts) {
|
|
|
43341
43412
|
tx.delete(gaTrafficWindowSummaries).where(eq44(gaTrafficWindowSummaries.projectId, project.id)).run();
|
|
43342
43413
|
for (const ws of windowSummaries) {
|
|
43343
43414
|
tx.insert(gaTrafficWindowSummaries).values({
|
|
43344
|
-
id:
|
|
43415
|
+
id: crypto35.randomUUID(),
|
|
43345
43416
|
projectId: project.id,
|
|
43346
43417
|
windowKey: ws.windowKey,
|
|
43347
43418
|
periodStart: ws.periodStart,
|
|
@@ -44022,7 +44093,7 @@ function parseSchemaPageEntry(entry) {
|
|
|
44022
44093
|
}
|
|
44023
44094
|
|
|
44024
44095
|
// ../integration-wordpress/src/wordpress-client.ts
|
|
44025
|
-
import
|
|
44096
|
+
import crypto36 from "crypto";
|
|
44026
44097
|
function validateUsername(username) {
|
|
44027
44098
|
if (!username || typeof username !== "string" || username.trim().length === 0) {
|
|
44028
44099
|
throw new WordpressApiError("AUTH_INVALID", "Username is required and must be a non-empty string", 400);
|
|
@@ -44242,7 +44313,7 @@ function buildSnippet(content) {
|
|
|
44242
44313
|
return `${text2.slice(0, 157)}...`;
|
|
44243
44314
|
}
|
|
44244
44315
|
function contentHash(content) {
|
|
44245
|
-
return
|
|
44316
|
+
return crypto36.createHash("sha256").update(content).digest("hex");
|
|
44246
44317
|
}
|
|
44247
44318
|
function buildAmbiguousSlugMessage(slug, pages) {
|
|
44248
44319
|
const candidates = pages.map((page) => {
|
|
@@ -45542,7 +45613,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
45542
45613
|
}
|
|
45543
45614
|
|
|
45544
45615
|
// ../api-routes/src/backlinks.ts
|
|
45545
|
-
import
|
|
45616
|
+
import crypto37 from "crypto";
|
|
45546
45617
|
import { and as and37, asc as asc9, desc as desc21, eq as eq45, sql as sql17 } from "drizzle-orm";
|
|
45547
45618
|
|
|
45548
45619
|
// ../integration-commoncrawl/src/constants.ts
|
|
@@ -46179,7 +46250,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
46179
46250
|
const refreshed = app.db.select().from(ccReleaseSyncs).where(eq45(ccReleaseSyncs.id, existing.id)).get();
|
|
46180
46251
|
return reply.status(200).send(mapSyncRow(refreshed));
|
|
46181
46252
|
}
|
|
46182
|
-
const id =
|
|
46253
|
+
const id = crypto37.randomUUID();
|
|
46183
46254
|
app.db.insert(ccReleaseSyncs).values({
|
|
46184
46255
|
id,
|
|
46185
46256
|
release,
|
|
@@ -46236,7 +46307,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
46236
46307
|
throw validationError("Invalid release id");
|
|
46237
46308
|
}
|
|
46238
46309
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
46239
|
-
const runId =
|
|
46310
|
+
const runId = crypto37.randomUUID();
|
|
46240
46311
|
app.db.insert(runs).values({
|
|
46241
46312
|
id: runId,
|
|
46242
46313
|
projectId: project.id,
|
|
@@ -46325,7 +46396,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
46325
46396
|
}
|
|
46326
46397
|
|
|
46327
46398
|
// ../api-routes/src/traffic.ts
|
|
46328
|
-
import
|
|
46399
|
+
import crypto39 from "crypto";
|
|
46329
46400
|
import { Agent as UndiciAgent } from "undici";
|
|
46330
46401
|
import { and as and38, desc as desc22, eq as eq46, gte as gte10, lte as lte9, sql as sql18 } from "drizzle-orm";
|
|
46331
46402
|
|
|
@@ -46346,7 +46417,7 @@ function resolveVercelSyncDeadlineMs(env = process.env) {
|
|
|
46346
46417
|
}
|
|
46347
46418
|
|
|
46348
46419
|
// ../integration-cloud-run/src/auth.ts
|
|
46349
|
-
import
|
|
46420
|
+
import crypto38 from "crypto";
|
|
46350
46421
|
var GOOGLE_TOKEN_URL3 = "https://oauth2.googleapis.com/token";
|
|
46351
46422
|
var CLOUD_LOGGING_READ_SCOPE = "https://www.googleapis.com/auth/logging.read";
|
|
46352
46423
|
var TOKEN_REQUEST_TIMEOUT_MS = 3e4;
|
|
@@ -46377,7 +46448,7 @@ function createServiceAccountJwt2(clientEmail, privateKey, scope) {
|
|
|
46377
46448
|
const headerB64 = encode(header);
|
|
46378
46449
|
const payloadB64 = encode(payload);
|
|
46379
46450
|
const signingInput = `${headerB64}.${payloadB64}`;
|
|
46380
|
-
const sign =
|
|
46451
|
+
const sign = crypto38.createSign("RSA-SHA256");
|
|
46381
46452
|
sign.update(signingInput);
|
|
46382
46453
|
const signature = sign.sign(privateKey, "base64url");
|
|
46383
46454
|
return `${signingInput}.${signature}`;
|
|
@@ -50354,7 +50425,7 @@ async function runBackfillTask(options) {
|
|
|
50354
50425
|
}
|
|
50355
50426
|
})();
|
|
50356
50427
|
tx.insert(rawEventSamples).values({
|
|
50357
|
-
id:
|
|
50428
|
+
id: crypto39.randomUUID(),
|
|
50358
50429
|
projectId: project.id,
|
|
50359
50430
|
sourceId: sourceRow2.id,
|
|
50360
50431
|
ts: sample.observedAt,
|
|
@@ -50483,7 +50554,7 @@ async function trafficRoutes(app, opts) {
|
|
|
50483
50554
|
}).where(eq46(trafficSources.id, activeSource.id)).run();
|
|
50484
50555
|
sourceRow2 = app.db.select().from(trafficSources).where(eq46(trafficSources.id, activeSource.id)).get();
|
|
50485
50556
|
} else {
|
|
50486
|
-
const newId =
|
|
50557
|
+
const newId = crypto39.randomUUID();
|
|
50487
50558
|
app.db.insert(trafficSources).values({
|
|
50488
50559
|
id: newId,
|
|
50489
50560
|
projectId: project.id,
|
|
@@ -50564,7 +50635,7 @@ async function trafficRoutes(app, opts) {
|
|
|
50564
50635
|
}).where(eq46(trafficSources.id, activeSource.id)).run();
|
|
50565
50636
|
sourceRow2 = app.db.select().from(trafficSources).where(eq46(trafficSources.id, activeSource.id)).get();
|
|
50566
50637
|
} else {
|
|
50567
|
-
const newId =
|
|
50638
|
+
const newId = crypto39.randomUUID();
|
|
50568
50639
|
app.db.insert(trafficSources).values({
|
|
50569
50640
|
id: newId,
|
|
50570
50641
|
projectId: project.id,
|
|
@@ -50648,7 +50719,7 @@ async function trafficRoutes(app, opts) {
|
|
|
50648
50719
|
}).where(eq46(trafficSources.id, activeSource.id)).run();
|
|
50649
50720
|
row = tx.select().from(trafficSources).where(eq46(trafficSources.id, activeSource.id)).get();
|
|
50650
50721
|
} else {
|
|
50651
|
-
const newId =
|
|
50722
|
+
const newId = crypto39.randomUUID();
|
|
50652
50723
|
tx.insert(trafficSources).values({
|
|
50653
50724
|
id: newId,
|
|
50654
50725
|
projectId: project.id,
|
|
@@ -50682,7 +50753,7 @@ async function trafficRoutes(app, opts) {
|
|
|
50682
50753
|
let created = false;
|
|
50683
50754
|
if (!existingSchedule) {
|
|
50684
50755
|
tx.insert(schedules).values({
|
|
50685
|
-
id:
|
|
50756
|
+
id: crypto39.randomUUID(),
|
|
50686
50757
|
projectId: project.id,
|
|
50687
50758
|
kind: SchedulableRunKinds["traffic-sync"],
|
|
50688
50759
|
cronExpr: DEFAULT_TRAFFIC_SYNC_CRON,
|
|
@@ -50737,7 +50808,7 @@ async function trafficRoutes(app, opts) {
|
|
|
50737
50808
|
const windowEnd = /* @__PURE__ */ new Date();
|
|
50738
50809
|
const startedAt = windowEnd.toISOString();
|
|
50739
50810
|
const syncStartedAtMs = windowEnd.getTime();
|
|
50740
|
-
const runId =
|
|
50811
|
+
const runId = crypto39.randomUUID();
|
|
50741
50812
|
app.db.insert(runs).values({
|
|
50742
50813
|
id: runId,
|
|
50743
50814
|
projectId: project.id,
|
|
@@ -51130,7 +51201,7 @@ async function trafficRoutes(app, opts) {
|
|
|
51130
51201
|
}
|
|
51131
51202
|
})();
|
|
51132
51203
|
tx.insert(rawEventSamples).values({
|
|
51133
|
-
id:
|
|
51204
|
+
id: crypto39.randomUUID(),
|
|
51134
51205
|
projectId: project.id,
|
|
51135
51206
|
sourceId: sourceRow2.id,
|
|
51136
51207
|
ts: sample.observedAt,
|
|
@@ -51381,7 +51452,7 @@ async function trafficRoutes(app, opts) {
|
|
|
51381
51452
|
};
|
|
51382
51453
|
}
|
|
51383
51454
|
const startedAt = windowEnd.toISOString();
|
|
51384
|
-
const runId =
|
|
51455
|
+
const runId = crypto39.randomUUID();
|
|
51385
51456
|
app.db.insert(runs).values({
|
|
51386
51457
|
id: runId,
|
|
51387
51458
|
projectId: project.id,
|
|
@@ -51751,7 +51822,7 @@ async function trafficRoutes(app, opts) {
|
|
|
51751
51822
|
}
|
|
51752
51823
|
|
|
51753
51824
|
// ../api-routes/src/doctor/checks/agent.ts
|
|
51754
|
-
import
|
|
51825
|
+
import crypto40 from "crypto";
|
|
51755
51826
|
import fs6 from "fs";
|
|
51756
51827
|
import path7 from "path";
|
|
51757
51828
|
var REQUIRED_SKILLS = ["canonry", "aero"];
|
|
@@ -51982,7 +52053,7 @@ function isInstalled(dir) {
|
|
|
51982
52053
|
}
|
|
51983
52054
|
function hashInstalledFile(filePath) {
|
|
51984
52055
|
try {
|
|
51985
|
-
return
|
|
52056
|
+
return crypto40.createHash("sha256").update(fs6.readFileSync(filePath)).digest("hex");
|
|
51986
52057
|
} catch {
|
|
51987
52058
|
return void 0;
|
|
51988
52059
|
}
|
|
@@ -54055,7 +54126,7 @@ async function doctorRoutes(app, opts) {
|
|
|
54055
54126
|
}
|
|
54056
54127
|
|
|
54057
54128
|
// ../api-routes/src/discovery/routes.ts
|
|
54058
|
-
import
|
|
54129
|
+
import crypto41 from "crypto";
|
|
54059
54130
|
import { and as and42, desc as desc23, eq as eq53, gte as gte12, inArray as inArray17, isNull as isNull4, or as or10 } from "drizzle-orm";
|
|
54060
54131
|
var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
|
|
54061
54132
|
async function discoveryRoutes(app, opts) {
|
|
@@ -54121,8 +54192,8 @@ async function discoveryRoutes(app, opts) {
|
|
|
54121
54192
|
if (existing && existing.runId) {
|
|
54122
54193
|
return { reused: true, sessionId: existing.id, runId: existing.runId };
|
|
54123
54194
|
}
|
|
54124
|
-
const sessionId =
|
|
54125
|
-
const runId =
|
|
54195
|
+
const sessionId = crypto41.randomUUID();
|
|
54196
|
+
const runId = crypto41.randomUUID();
|
|
54126
54197
|
tx.insert(discoverySessions).values({
|
|
54127
54198
|
id: sessionId,
|
|
54128
54199
|
projectId: project.id,
|
|
@@ -54376,7 +54447,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
54376
54447
|
app.db.transaction((tx) => {
|
|
54377
54448
|
for (const query of promotedQueries) {
|
|
54378
54449
|
tx.insert(queries).values({
|
|
54379
|
-
id:
|
|
54450
|
+
id: crypto41.randomUUID(),
|
|
54380
54451
|
projectId: project.id,
|
|
54381
54452
|
query,
|
|
54382
54453
|
provenance,
|
|
@@ -54385,7 +54456,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
54385
54456
|
}
|
|
54386
54457
|
for (const domain of promotedCompetitors) {
|
|
54387
54458
|
tx.insert(competitors).values({
|
|
54388
|
-
id:
|
|
54459
|
+
id: crypto41.randomUUID(),
|
|
54389
54460
|
projectId: project.id,
|
|
54390
54461
|
domain,
|
|
54391
54462
|
provenance,
|
|
@@ -54475,7 +54546,7 @@ function selectEligibleCompetitors(competitorMap, competitorTypes) {
|
|
|
54475
54546
|
}
|
|
54476
54547
|
|
|
54477
54548
|
// ../api-routes/src/discovery/orchestrate.ts
|
|
54478
|
-
import
|
|
54549
|
+
import crypto42 from "crypto";
|
|
54479
54550
|
import { eq as eq54 } from "drizzle-orm";
|
|
54480
54551
|
var DEFAULT_MAX_PROBES = 100;
|
|
54481
54552
|
var ABSOLUTE_MAX_PROBES = 500;
|
|
@@ -54643,7 +54714,7 @@ async function executeDiscovery(opts) {
|
|
|
54643
54714
|
probeRows.push({ citedDomains: probe.citedDomains, bucket });
|
|
54644
54715
|
buckets[bucket]++;
|
|
54645
54716
|
return {
|
|
54646
|
-
id:
|
|
54717
|
+
id: crypto42.randomUUID(),
|
|
54647
54718
|
sessionId: opts.sessionId,
|
|
54648
54719
|
projectId: opts.project.id,
|
|
54649
54720
|
query: probedCanonicals[index2],
|
|
@@ -54695,7 +54766,7 @@ function upsertDomainClassifications(db, projectId, sessionId, competitorMap) {
|
|
|
54695
54766
|
const domain = hostOf(entry.domain) ?? "";
|
|
54696
54767
|
if (!domain) continue;
|
|
54697
54768
|
db.insert(domainClassifications).values({
|
|
54698
|
-
id:
|
|
54769
|
+
id: crypto42.randomUUID(),
|
|
54699
54770
|
projectId,
|
|
54700
54771
|
domain,
|
|
54701
54772
|
competitorType: entry.competitorType,
|
|
@@ -54735,7 +54806,7 @@ function dedupeStrings(input) {
|
|
|
54735
54806
|
}
|
|
54736
54807
|
|
|
54737
54808
|
// ../api-routes/src/technical-aeo.ts
|
|
54738
|
-
import
|
|
54809
|
+
import crypto43 from "crypto";
|
|
54739
54810
|
import { and as and43, asc as asc10, count, desc as desc24, eq as eq55, inArray as inArray18, lt as lt7 } from "drizzle-orm";
|
|
54740
54811
|
var SURFACEABLE_STATUSES = [RunStatuses.completed, RunStatuses.partial];
|
|
54741
54812
|
function emptyScore(projectName) {
|
|
@@ -54871,7 +54942,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
54871
54942
|
return { runId: existing.id, status: existing.status };
|
|
54872
54943
|
}
|
|
54873
54944
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
54874
|
-
const runId =
|
|
54945
|
+
const runId = crypto43.randomUUID();
|
|
54875
54946
|
app.db.insert(runs).values({
|
|
54876
54947
|
id: runId,
|
|
54877
54948
|
projectId: project.id,
|
|
@@ -54889,7 +54960,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
54889
54960
|
}
|
|
54890
54961
|
|
|
54891
54962
|
// ../api-routes/src/research.ts
|
|
54892
|
-
import
|
|
54963
|
+
import crypto44 from "crypto";
|
|
54893
54964
|
import { and as and44, desc as desc25, eq as eq56 } from "drizzle-orm";
|
|
54894
54965
|
var sameLocation = (a, b) => a.label === b.label && a.city === b.city && a.region === b.region && a.country === b.country && a.timezone === b.timezone;
|
|
54895
54966
|
async function researchRoutes(app, opts) {
|
|
@@ -54916,7 +54987,7 @@ async function researchRoutes(app, opts) {
|
|
|
54916
54987
|
if (!adapter.modelValidationPattern.test(resolvedModel)) throw validationError(`Invalid resolved model "${resolvedModel}" for provider "${providerName}".`, { provider: providerName, model: resolvedModel, hint: adapter.modelValidationHint });
|
|
54917
54988
|
if (new Set(input.queries.map((query) => query.toLocaleLowerCase())).size !== input.queries.length) throw validationError("Research queries must be unique within a batch.");
|
|
54918
54989
|
const normalized = { queries: input.queries, provider: providerName, model: requestedModel, location: location ?? null };
|
|
54919
|
-
const requestHash2 =
|
|
54990
|
+
const requestHash2 = crypto44.createHash("sha256").update(JSON.stringify(normalized)).digest("hex");
|
|
54920
54991
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
54921
54992
|
const decision = app.db.transaction((tx) => {
|
|
54922
54993
|
if (input.idempotencyKey) {
|
|
@@ -54926,9 +54997,9 @@ async function researchRoutes(app, opts) {
|
|
|
54926
54997
|
return { reused: true, id: existing.id, shouldDispatch: existing.status === ResearchRunStatuses.queued };
|
|
54927
54998
|
}
|
|
54928
54999
|
}
|
|
54929
|
-
const id =
|
|
55000
|
+
const id = crypto44.randomUUID();
|
|
54930
55001
|
tx.insert(researchRuns).values({ id, projectId: project.id, status: ResearchRunStatuses.queued, provider: providerName, requestedModel, resolvedModel, location: location ?? null, totalQueries: input.queries.length, idempotencyKey: input.idempotencyKey ?? null, requestHash: input.idempotencyKey ? requestHash2 : null, createdAt: now }).run();
|
|
54931
|
-
for (const [position, query] of input.queries.entries()) tx.insert(researchRunQueries).values({ id:
|
|
55002
|
+
for (const [position, query] of input.queries.entries()) tx.insert(researchRunQueries).values({ id: crypto44.randomUUID(), researchRunId: id, position, queryText: query, status: ResearchQueryStatuses.queued, requestedModel, resolvedModel, groundingSources: [], citedDomains: [], searchQueries: [], createdAt: now }).run();
|
|
54932
55003
|
writeAuditLog(tx, { projectId: project.id, actor: "api", action: "research.created", entityType: "research_run", entityId: id });
|
|
54933
55004
|
return { reused: false, id, shouldDispatch: true };
|
|
54934
55005
|
});
|
|
@@ -55345,7 +55416,7 @@ function buildTrafficSourceValidators(opts) {
|
|
|
55345
55416
|
}
|
|
55346
55417
|
|
|
55347
55418
|
// src/intelligence-service.ts
|
|
55348
|
-
import
|
|
55419
|
+
import crypto45 from "crypto";
|
|
55349
55420
|
|
|
55350
55421
|
// src/logger.ts
|
|
55351
55422
|
var IS_TTY = process.stdout.isTTY === true;
|
|
@@ -55986,7 +56057,7 @@ var IntelligenceService = class {
|
|
|
55986
56057
|
}).run();
|
|
55987
56058
|
}
|
|
55988
56059
|
tx.insert(healthSnapshots).values({
|
|
55989
|
-
id:
|
|
56060
|
+
id: crypto45.randomUUID(),
|
|
55990
56061
|
projectId,
|
|
55991
56062
|
runId,
|
|
55992
56063
|
overallCitedRate: String(result.health.overallCitedRate),
|
|
@@ -4019,6 +4019,14 @@ var measurementPropertyProviderRowSchema = z5.object({
|
|
|
4019
4019
|
mentionCoverage: measurementMetricValueSchema,
|
|
4020
4020
|
citationCoverage: measurementMetricValueSchema
|
|
4021
4021
|
}).strict();
|
|
4022
|
+
var measurementOutcomeCountsSchema = z5.object({
|
|
4023
|
+
bothSignals: z5.number().int().nonnegative(),
|
|
4024
|
+
mentionedOnly: z5.number().int().nonnegative(),
|
|
4025
|
+
citedOnly: z5.number().int().nonnegative(),
|
|
4026
|
+
neither: z5.number().int().nonnegative(),
|
|
4027
|
+
notMeasured: z5.number().int().nonnegative(),
|
|
4028
|
+
total: z5.number().int().nonnegative()
|
|
4029
|
+
}).strict();
|
|
4022
4030
|
var measurementPropertyRowSchema = z5.object({
|
|
4023
4031
|
targetKey: measurementV2StableKeySchema,
|
|
4024
4032
|
label: z5.string().min(1),
|
|
@@ -4076,6 +4084,13 @@ var measurementOverviewResponseSchema = z5.object({
|
|
|
4076
4084
|
)
|
|
4077
4085
|
}).strict(),
|
|
4078
4086
|
properties: measurementCursorPageSchema(measurementPropertyRowSchema),
|
|
4087
|
+
/**
|
|
4088
|
+
* Outcome split over the whole RESULT SET, not the page — so paging through
|
|
4089
|
+
* does not move it. It narrows with `search` exactly as `properties.totalEstimate`
|
|
4090
|
+
* does, because both are computed from the same filtered rows; with no search
|
|
4091
|
+
* that result set is the entire scope.
|
|
4092
|
+
*/
|
|
4093
|
+
outcomes: measurementOutcomeCountsSchema,
|
|
4079
4094
|
flags: z5.object({ total: z5.number().int().nonnegative() }).strict(),
|
|
4080
4095
|
namedShareOfVoice: measurementNamedShareOfVoiceSchema.optional()
|
|
4081
4096
|
}).strict();
|