@ainyc/canonry 4.74.0 → 4.76.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/README.md +1 -1
- package/assets/agent-workspace/skills/aero/references/orchestration.md +1 -1
- package/assets/agent-workspace/skills/canonry/SKILL.md +1 -1
- package/assets/assets/{BacklinksPage-ClgP7CUd.js → BacklinksPage-Dvc3mk9A.js} +1 -1
- package/assets/assets/{ChartPrimitives-PGDrQBXP.js → ChartPrimitives-DbjEIcrG.js} +1 -1
- package/assets/assets/{ProjectPage-xfLeh2vB.js → ProjectPage-CeZYtdbm.js} +6 -6
- package/assets/assets/{RunRow-DL-lUm35.js → RunRow-CgojRiy8.js} +1 -1
- package/assets/assets/{RunsPage-BCL_lU-R.js → RunsPage-CWEcQv7p.js} +1 -1
- package/assets/assets/{SettingsPage-D67UQYJa.js → SettingsPage-CCT4jasH.js} +1 -1
- package/assets/assets/{TrafficPage-DVRcPxCk.js → TrafficPage-DtdlxDFZ.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-JzX1fhGQ.js → TrafficSourceDetailPage-CPBuL-HQ.js} +1 -1
- package/assets/assets/{extract-error-message-Cia_CilL.js → extract-error-message--ubvhQzu.js} +1 -1
- package/assets/assets/{index-DHg9_-PB.js → index-CKbfZ6rA.js} +36 -36
- package/assets/assets/{index-CFVX11lK.css → index-DRhoqa2-.css} +1 -1
- package/assets/assets/{server-traffic-GBmLS3L7.js → server-traffic-Dskh-6z1.js} +1 -1
- package/assets/assets/{trash-2-Bk7PYGBN.js → trash-2-b62WCytM.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-A7JX3FZB.js → chunk-JNAKRK77.js} +9 -3
- package/dist/{chunk-ZRZHIS22.js → chunk-JUWU2DV6.js} +20 -10
- package/dist/{chunk-MRC4JMIH.js → chunk-QY5WZWU4.js} +38 -30
- package/dist/{chunk-W6GBIRFA.js → chunk-WFMEK34V.js} +1 -1
- package/dist/cli.js +5 -5
- package/dist/index.d.ts +10 -0
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-GPO2VMEC.js → intelligence-service-L2A5MFB4.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as d,j as i,c4 as S,b_ as l,c5 as v,ay as y,l as t,c6 as m,b$ as a,c7 as T,c8 as h,c9 as p,ca as C}from"./index-
|
|
1
|
+
import{c as d,j as i,c4 as S,b_ as l,c5 as v,ay as y,l as t,c6 as m,b$ as a,c7 as T,c8 as h,c9 as p,ca as C}from"./index-CKbfZ6rA.js";import{u as c,r as g,n as s,o as u}from"./vendor-tanstack-Dq7p98wZ.js";const w=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],P=d("refresh-cw",w);function k(e){switch(e){case a.connected:return"positive";case a.paused:return"caution";case a.error:return"negative";case a.archived:return"neutral"}}function q(e){const r={};return e.kind&&e.kind!=="all"&&(r.kind=e.kind),e.sourceId&&(r.sourceId=e.sourceId),e.sinceMinutes!==void 0&&(r.since=new Date(Date.now()-e.sinceMinutes*6e4).toISOString()),e.limit!==void 0&&(r.limit=String(e.limit)),r}function o(e){e.invalidateQueries({predicate:r=>{const n=r.queryKey[0];return typeof n?._id=="string"&&n._id.startsWith("getApiV1ProjectsByNameTraffic")}})}function F(e){return c({...S({client:t,path:{name:e??""}}),enabled:!!e,staleTime:i})}function V(e){return c({...C({client:t,path:{name:e??""}}),enabled:!!e,staleTime:i})}function b(e,r){return c({...l({client:t,path:{name:e??"",id:r??""}}),enabled:!!(e&&r),staleTime:i})}function A(e,r){const n=g.useMemo(()=>q(r),[r.kind,r.sourceId,r.sinceMinutes,r.limit]);return c({...v({client:t,path:{name:e??""},query:n}),enabled:!!e,staleTime:i})}function E(e){const r=s();return u({mutationFn:n=>{if(!e)throw new Error("Project is required to connect a Cloud Run source");return p(e,n)},onSuccess:()=>{e&&o(r)}})}function I(e){const r=s();return u({mutationFn:n=>{if(!e)throw new Error("Project is required to connect a WordPress source");return T(e,n)},onSuccess:()=>{e&&o(r)}})}function Q(e){const r=s();return u({mutationFn:n=>{if(!e)throw new Error("Project is required to connect a Vercel source");return h(e,n)},onSuccess:()=>{e&&o(r)}})}function R(e,r){const n=s();return u({mutationFn:f=>{if(!e||!r)throw new Error("Project and sourceId are required to sync");return m(e,r,f??void 0)},onSuccess:()=>{e&&(o(n),n.invalidateQueries({queryKey:y({client:t})}))}})}export{P as R,I as a,Q as b,E as c,F as d,b as e,A as f,R as g,k as t,V as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c}from"./index-
|
|
1
|
+
import{c}from"./index-CKbfZ6rA.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],n=c("circle-question-mark",e);const o=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=c("download",o);const t=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n as a};
|
package/assets/index.html
CHANGED
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
|
|
13
13
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
14
14
|
<title>Canonry</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-CKbfZ6rA.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Dq7p98wZ.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="./assets/vendor-radix-B57xfQbP.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="./assets/vendor-recharts-ClRVR6aX.js">
|
|
19
19
|
<link rel="modulepreload" crossorigin href="./assets/vendor-markdown-DK7fbRNb.js">
|
|
20
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
20
|
+
<link rel="stylesheet" crossorigin href="./assets/index-DRhoqa2-.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
|
23
23
|
<div id="root"></div>
|
|
@@ -35,8 +35,8 @@ function notFound(entity, id) {
|
|
|
35
35
|
function validationError(message, details) {
|
|
36
36
|
return new AppError("VALIDATION_ERROR", message, 400, details);
|
|
37
37
|
}
|
|
38
|
-
function authRequired() {
|
|
39
|
-
return new AppError("AUTH_REQUIRED",
|
|
38
|
+
function authRequired(message = "Authentication required") {
|
|
39
|
+
return new AppError("AUTH_REQUIRED", message, 401);
|
|
40
40
|
}
|
|
41
41
|
function authInvalid() {
|
|
42
42
|
return new AppError("AUTH_INVALID", "Invalid API key", 401);
|
|
@@ -4283,6 +4283,11 @@ var AI_PROVIDER_INFRA_DOMAINS = [
|
|
|
4283
4283
|
VERTEX_AI_SEARCH_PROXY_DOMAIN
|
|
4284
4284
|
];
|
|
4285
4285
|
|
|
4286
|
+
// ../contracts/src/sql-like.ts
|
|
4287
|
+
function escapeLikePattern(value) {
|
|
4288
|
+
return value.replace(/[\\%_]/g, (match) => `\\${match}`);
|
|
4289
|
+
}
|
|
4290
|
+
|
|
4286
4291
|
export {
|
|
4287
4292
|
__export,
|
|
4288
4293
|
apiKeyDtoSchema,
|
|
@@ -4546,5 +4551,6 @@ export {
|
|
|
4546
4551
|
AI_ENGINE_DOMAINS,
|
|
4547
4552
|
AI_ENGINE_SELF_DOMAINS,
|
|
4548
4553
|
VERTEX_AI_SEARCH_PROXY_DOMAIN,
|
|
4549
|
-
AI_PROVIDER_INFRA_DOMAINS
|
|
4554
|
+
AI_PROVIDER_INFRA_DOMAINS,
|
|
4555
|
+
escapeLikePattern
|
|
4550
4556
|
};
|
|
@@ -101,6 +101,7 @@ import {
|
|
|
101
101
|
effectiveBrandNames,
|
|
102
102
|
effectiveDomains,
|
|
103
103
|
emptyCitationVisibility,
|
|
104
|
+
escapeLikePattern,
|
|
104
105
|
extractAnswerMentions,
|
|
105
106
|
findDuplicateLocationLabels,
|
|
106
107
|
forbidden,
|
|
@@ -229,7 +230,7 @@ import {
|
|
|
229
230
|
wordpressSchemaDeployResultDtoSchema,
|
|
230
231
|
wordpressSchemaStatusResultDtoSchema,
|
|
231
232
|
wordpressStatusDtoSchema
|
|
232
|
-
} from "./chunk-
|
|
233
|
+
} from "./chunk-JNAKRK77.js";
|
|
233
234
|
|
|
234
235
|
// src/intelligence-service.ts
|
|
235
236
|
import { eq as eq33, desc as desc17, asc as asc4, and as and24, ne as ne5, or as or5, inArray as inArray12, gte as gte6, lte as lte3 } from "drizzle-orm";
|
|
@@ -5029,7 +5030,7 @@ var SKIP_PATHS = ["/health"];
|
|
|
5029
5030
|
function shouldSkipAuth(url) {
|
|
5030
5031
|
if (SKIP_PATHS.includes(url)) return true;
|
|
5031
5032
|
if (url.endsWith("/openapi.json")) return true;
|
|
5032
|
-
if (url.
|
|
5033
|
+
if (url.endsWith("/google/callback")) return true;
|
|
5033
5034
|
if (url.endsWith("/session") || url.endsWith("/session/setup")) return true;
|
|
5034
5035
|
return false;
|
|
5035
5036
|
}
|
|
@@ -7473,10 +7474,10 @@ function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt) {
|
|
|
7473
7474
|
const latest = new Date(projectRuns[projectRuns.length - 1].createdAt);
|
|
7474
7475
|
const buckets = [];
|
|
7475
7476
|
let start = new Date(earliest);
|
|
7476
|
-
start.
|
|
7477
|
+
start.setUTCHours(0, 0, 0, 0);
|
|
7477
7478
|
while (start <= latest) {
|
|
7478
7479
|
const end = new Date(start);
|
|
7479
|
-
end.
|
|
7480
|
+
end.setUTCDate(end.getUTCDate() + bucketDays);
|
|
7480
7481
|
const startISO = start.toISOString();
|
|
7481
7482
|
const endISO = end.toISOString();
|
|
7482
7483
|
const inBucket = snapshots.filter((s) => s.createdAt >= startISO && s.createdAt < endISO);
|
|
@@ -12575,9 +12576,6 @@ function clampSearchLimit(raw) {
|
|
|
12575
12576
|
if (parsed > SEARCH_HIT_HARD_LIMIT) return SEARCH_HIT_HARD_LIMIT;
|
|
12576
12577
|
return parsed;
|
|
12577
12578
|
}
|
|
12578
|
-
function escapeLikePattern(value) {
|
|
12579
|
-
return value.replace(/[\\%_]/g, (match) => `\\${match}`);
|
|
12580
|
-
}
|
|
12581
12579
|
function summarizeRun(run) {
|
|
12582
12580
|
return {
|
|
12583
12581
|
id: run.id,
|
|
@@ -19400,8 +19398,8 @@ async function googleRoutes(app, opts) {
|
|
|
19400
19398
|
if (startDate) conditions.push(sql8`${gscSearchData.date} >= ${startDate}`);
|
|
19401
19399
|
else if (cutoffDate) conditions.push(sql8`${gscSearchData.date} >= ${cutoffDate}`);
|
|
19402
19400
|
if (endDate) conditions.push(sql8`${gscSearchData.date} <= ${endDate}`);
|
|
19403
|
-
if (query) conditions.push(sql8`${gscSearchData.query} LIKE ${"%" + query + "%"}`);
|
|
19404
|
-
if (page) conditions.push(sql8`${gscSearchData.page} LIKE ${"%" + page + "%"}`);
|
|
19401
|
+
if (query) conditions.push(sql8`${gscSearchData.query} LIKE ${"%" + escapeLikePattern(query) + "%"} ESCAPE '\\'`);
|
|
19402
|
+
if (page) conditions.push(sql8`${gscSearchData.page} LIKE ${"%" + escapeLikePattern(page) + "%"} ESCAPE '\\'`);
|
|
19405
19403
|
const limitVal = Math.max(parseInt(limit ?? "500", 10) || 0, 1);
|
|
19406
19404
|
const offsetVal = Math.max(parseInt(offset ?? "0", 10) || 0, 0);
|
|
19407
19405
|
const rows = app.db.select().from(gscSearchData).where(and13(...conditions)).orderBy(desc10(gscSearchData.date)).limit(limitVal).offset(offsetVal).all();
|
|
@@ -23015,10 +23013,17 @@ async function withWordpressErrorHandling(handler) {
|
|
|
23015
23013
|
}
|
|
23016
23014
|
}
|
|
23017
23015
|
async function wordpressRoutes(app, opts) {
|
|
23016
|
+
const allowLoopback = opts.allowLoopbackWebhooks === true;
|
|
23018
23017
|
function requireStore() {
|
|
23019
23018
|
if (opts.wordpressConnectionStore) return opts.wordpressConnectionStore;
|
|
23020
23019
|
throw validationError("WordPress connection storage is not configured for this deployment");
|
|
23021
23020
|
}
|
|
23021
|
+
async function assertWordpressUrlAllowed(rawUrl, field) {
|
|
23022
|
+
const check = await resolveWebhookTarget(rawUrl, { allowLoopback });
|
|
23023
|
+
if (!check.ok) {
|
|
23024
|
+
throw validationError(`${field} ${check.message.replace(/^"url" /, "")}`);
|
|
23025
|
+
}
|
|
23026
|
+
}
|
|
23022
23027
|
function requireConnection(store, projectName) {
|
|
23023
23028
|
const connection = store.getConnection(projectName);
|
|
23024
23029
|
if (!connection) {
|
|
@@ -23038,6 +23043,8 @@ async function wordpressRoutes(app, opts) {
|
|
|
23038
23043
|
if (defaultEnv === "staging" && !stagingUrl) {
|
|
23039
23044
|
throw validationError('defaultEnv "staging" requires stagingUrl');
|
|
23040
23045
|
}
|
|
23046
|
+
await assertWordpressUrlAllowed(url, "url");
|
|
23047
|
+
if (stagingUrl) await assertWordpressUrlAllowed(stagingUrl, "stagingUrl");
|
|
23041
23048
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
23042
23049
|
const existing = store.getConnection(project.name);
|
|
23043
23050
|
const nextConnection = {
|
|
@@ -23366,6 +23373,8 @@ async function wordpressRoutes(app, opts) {
|
|
|
23366
23373
|
if (defaultEnv === "staging" && !stagingUrl) {
|
|
23367
23374
|
throw validationError('defaultEnv "staging" requires stagingUrl');
|
|
23368
23375
|
}
|
|
23376
|
+
await assertWordpressUrlAllowed(url, "url");
|
|
23377
|
+
if (stagingUrl) await assertWordpressUrlAllowed(stagingUrl, "stagingUrl");
|
|
23369
23378
|
const steps = [];
|
|
23370
23379
|
let connection = null;
|
|
23371
23380
|
let pageUrls = [];
|
|
@@ -32107,7 +32116,8 @@ async function apiRoutes(app, opts) {
|
|
|
32107
32116
|
});
|
|
32108
32117
|
await api.register(wordpressRoutes, {
|
|
32109
32118
|
wordpressConnectionStore: opts.wordpressConnectionStore,
|
|
32110
|
-
routePrefix: opts.routePrefix ?? "/api/v1"
|
|
32119
|
+
routePrefix: opts.routePrefix ?? "/api/v1",
|
|
32120
|
+
allowLoopbackWebhooks: opts.allowLoopbackWebhooks
|
|
32111
32121
|
});
|
|
32112
32122
|
await api.register(cdpRoutes, {
|
|
32113
32123
|
getCdpStatus: opts.getCdpStatus,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
loadConfig,
|
|
10
10
|
loadConfigRaw,
|
|
11
11
|
saveConfigPatch
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-WFMEK34V.js";
|
|
13
13
|
import {
|
|
14
14
|
CC_CACHE_DIR,
|
|
15
15
|
DUCKDB_SPEC,
|
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
siteAuditPages,
|
|
98
98
|
siteAuditSnapshots,
|
|
99
99
|
usageCounters
|
|
100
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-JUWU2DV6.js";
|
|
101
101
|
import {
|
|
102
102
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
103
103
|
AGENT_PROVIDER_IDS,
|
|
@@ -127,6 +127,7 @@ import {
|
|
|
127
127
|
agentMemoryDeleteRequestSchema,
|
|
128
128
|
agentMemoryUpsertRequestSchema,
|
|
129
129
|
authInvalid,
|
|
130
|
+
authRequired,
|
|
130
131
|
buildRunErrorFromMessages,
|
|
131
132
|
classifySkillFile,
|
|
132
133
|
coerceSkillManifest,
|
|
@@ -148,7 +149,7 @@ import {
|
|
|
148
149
|
validationError,
|
|
149
150
|
winnabilityClassLabel,
|
|
150
151
|
withRetry
|
|
151
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-JNAKRK77.js";
|
|
152
153
|
|
|
153
154
|
// src/telemetry.ts
|
|
154
155
|
import crypto from "crypto";
|
|
@@ -4068,31 +4069,10 @@ import { eq as eq4, and as and4 } from "drizzle-orm";
|
|
|
4068
4069
|
var log4 = createLogger("SitemapParser");
|
|
4069
4070
|
var LOC_REGEX = /<loc>([^<]+)<\/loc>/gi;
|
|
4070
4071
|
var SITEMAP_TAG_REGEX = /<sitemap>[\s\S]*?<\/sitemap>/gi;
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
// private class A
|
|
4076
|
-
/^172\.(1[6-9]|2\d|3[01])\./,
|
|
4077
|
-
// private class B
|
|
4078
|
-
/^192\.168\./
|
|
4079
|
-
// private class C
|
|
4080
|
-
];
|
|
4081
|
-
function validateSitemapUrl(url) {
|
|
4082
|
-
let parsed;
|
|
4083
|
-
try {
|
|
4084
|
-
parsed = new URL(url);
|
|
4085
|
-
} catch {
|
|
4086
|
-
throw new Error(`Invalid sitemap URL: ${url}`);
|
|
4087
|
-
}
|
|
4088
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
4089
|
-
throw new Error(`Sitemap URL must use http or https protocol: ${url}`);
|
|
4090
|
-
}
|
|
4091
|
-
const host = parsed.hostname.toLowerCase();
|
|
4092
|
-
for (const pattern of PRIVATE_IP_PATTERNS) {
|
|
4093
|
-
if (pattern.test(host)) {
|
|
4094
|
-
throw new Error(`Sitemap URL points to a private or reserved IP range: ${url}`);
|
|
4095
|
-
}
|
|
4072
|
+
async function validateSitemapUrl(url) {
|
|
4073
|
+
const check = await resolveWebhookTarget(url, { allowLoopback: true });
|
|
4074
|
+
if (!check.ok) {
|
|
4075
|
+
throw new Error(`Sitemap URL rejected: ${check.message.replace(/^"url" /, "")} (${url})`);
|
|
4096
4076
|
}
|
|
4097
4077
|
}
|
|
4098
4078
|
async function readSitemapBody(res) {
|
|
@@ -4122,9 +4102,9 @@ async function parseSitemapRecursive(url, urls, visited, depth, isChild) {
|
|
|
4122
4102
|
if (depth > 3) return;
|
|
4123
4103
|
if (visited.has(url)) return;
|
|
4124
4104
|
visited.add(url);
|
|
4125
|
-
validateSitemapUrl(url);
|
|
4126
4105
|
let res;
|
|
4127
4106
|
try {
|
|
4107
|
+
await validateSitemapUrl(url);
|
|
4128
4108
|
res = await fetch(url);
|
|
4129
4109
|
} catch (err) {
|
|
4130
4110
|
if (!isChild) throw err;
|
|
@@ -5176,6 +5156,12 @@ function toHomepageUrl(canonicalDomain) {
|
|
|
5176
5156
|
const trimmed = canonicalDomain.trim().replace(/\/+$/, "");
|
|
5177
5157
|
return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
5178
5158
|
}
|
|
5159
|
+
async function assertSiteAuditUrlAllowed(rawUrl, field) {
|
|
5160
|
+
const check = await resolveWebhookTarget(rawUrl);
|
|
5161
|
+
if (!check.ok) {
|
|
5162
|
+
throw new Error(`${field} ${check.message.replace(/^"url" /, "")}`);
|
|
5163
|
+
}
|
|
5164
|
+
}
|
|
5179
5165
|
function clampSiteAuditLimit(limit) {
|
|
5180
5166
|
if (limit == null || !Number.isFinite(limit)) return SITE_AUDIT_DEFAULT_PAGE_LIMIT;
|
|
5181
5167
|
return Math.max(1, Math.min(SITE_AUDIT_MAX_PAGE_LIMIT, Math.floor(limit)));
|
|
@@ -5233,6 +5219,8 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
|
|
|
5233
5219
|
const homepageUrl = toHomepageUrl(project.canonicalDomain);
|
|
5234
5220
|
const limit = clampSiteAuditLimit(opts.limit);
|
|
5235
5221
|
log11.info("start", { runId, projectId, homepageUrl, sitemapUrl: opts.sitemapUrl ?? null, limit });
|
|
5222
|
+
await assertSiteAuditUrlAllowed(homepageUrl, "canonicalDomain");
|
|
5223
|
+
if (opts.sitemapUrl) await assertSiteAuditUrlAllowed(opts.sitemapUrl, "sitemapUrl");
|
|
5236
5224
|
const report = await runSitemapAudit(homepageUrl, { sitemapUrl: opts.sitemapUrl, limit });
|
|
5237
5225
|
const successCount = report.pages.filter((page) => page.status === "success").length;
|
|
5238
5226
|
const pagesErrored = report.pages.filter((page) => page.status === "error").length;
|
|
@@ -5773,7 +5761,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
5773
5761
|
return result;
|
|
5774
5762
|
}
|
|
5775
5763
|
async function backfillInsightsCommand(project, opts) {
|
|
5776
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
5764
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-L2A5MFB4.js");
|
|
5777
5765
|
const config = loadConfig();
|
|
5778
5766
|
const db = createClient(config.database);
|
|
5779
5767
|
migrate(db);
|
|
@@ -9592,6 +9580,13 @@ function applyLegacyCredentials(rows, config) {
|
|
|
9592
9580
|
log18.info("credentials.migrated", { type: "ga4", count: migratedGa4 });
|
|
9593
9581
|
}
|
|
9594
9582
|
}
|
|
9583
|
+
function isLoopbackBindHost(host) {
|
|
9584
|
+
if (host == null || host === "") return true;
|
|
9585
|
+
const normalized = host.trim().toLowerCase().replace(/^\[|\]$/g, "");
|
|
9586
|
+
if (normalized === "localhost" || normalized === "::1") return true;
|
|
9587
|
+
if (/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(normalized)) return true;
|
|
9588
|
+
return false;
|
|
9589
|
+
}
|
|
9595
9590
|
async function createServer(opts) {
|
|
9596
9591
|
const logger = opts.logger === false ? false : process.stdout.isTTY ? {
|
|
9597
9592
|
transport: {
|
|
@@ -9994,6 +9989,15 @@ async function createServer(opts) {
|
|
|
9994
9989
|
}));
|
|
9995
9990
|
return true;
|
|
9996
9991
|
};
|
|
9992
|
+
const boundToLoopback = isLoopbackBindHost(opts.host);
|
|
9993
|
+
const requestHasValidApiKey = (request) => {
|
|
9994
|
+
const header = request.headers.authorization;
|
|
9995
|
+
if (!header) return false;
|
|
9996
|
+
const parts = header.split(" ");
|
|
9997
|
+
if (parts.length !== 2 || parts[0] !== "Bearer") return false;
|
|
9998
|
+
const key = opts.db.select().from(apiKeys).where(eq18(apiKeys.keyHash, hashApiKey(parts[1]))).get();
|
|
9999
|
+
return Boolean(key && !key.revokedAt);
|
|
10000
|
+
};
|
|
9997
10001
|
app.get(apiPrefix + "/session", async (request, reply) => {
|
|
9998
10002
|
const sessionId = parseCookies(request.headers.cookie)[SESSION_COOKIE_NAME];
|
|
9999
10003
|
return reply.send({
|
|
@@ -10002,6 +10006,10 @@ async function createServer(opts) {
|
|
|
10002
10006
|
});
|
|
10003
10007
|
});
|
|
10004
10008
|
app.post(apiPrefix + "/session/setup", async (request, reply) => {
|
|
10009
|
+
if (!boundToLoopback && !requestHasValidApiKey(request)) {
|
|
10010
|
+
const err = authRequired("This server is network-reachable; setting the dashboard password requires a valid API key.");
|
|
10011
|
+
return reply.status(err.statusCode).send(err.toJSON());
|
|
10012
|
+
}
|
|
10005
10013
|
if (opts.config.dashboardPasswordHash) {
|
|
10006
10014
|
const err = validationError("Dashboard password is already configured");
|
|
10007
10015
|
return reply.status(err.statusCode).send(err.toJSON());
|
package/dist/cli.js
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
setTelemetrySource,
|
|
28
28
|
showFirstRunNotice,
|
|
29
29
|
trackEvent
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-QY5WZWU4.js";
|
|
31
31
|
import {
|
|
32
32
|
CliError,
|
|
33
33
|
EXIT_SYSTEM_ERROR,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
saveConfig,
|
|
45
45
|
saveConfigPatch,
|
|
46
46
|
usageError
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-WFMEK34V.js";
|
|
48
48
|
import {
|
|
49
49
|
apiKeys,
|
|
50
50
|
createClient,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
projects,
|
|
53
53
|
queries,
|
|
54
54
|
renderReportHtml
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-JUWU2DV6.js";
|
|
56
56
|
import {
|
|
57
57
|
CcReleaseSyncStatuses,
|
|
58
58
|
CheckScopes,
|
|
@@ -72,7 +72,7 @@ import {
|
|
|
72
72
|
providerQuotaPolicySchema,
|
|
73
73
|
resolveProviderInput,
|
|
74
74
|
winnabilityClassSchema
|
|
75
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-JNAKRK77.js";
|
|
76
76
|
|
|
77
77
|
// src/cli.ts
|
|
78
78
|
import { pathToFileURL } from "url";
|
|
@@ -10376,7 +10376,7 @@ async function serveCommand(format = "text") {
|
|
|
10376
10376
|
process.stderr.write(`warning: ai-referral-paths backfill skipped: ${msg}
|
|
10377
10377
|
`);
|
|
10378
10378
|
}
|
|
10379
|
-
const app = await createServer({ config, db });
|
|
10379
|
+
const app = await createServer({ config, db, host });
|
|
10380
10380
|
let shuttingDown = false;
|
|
10381
10381
|
const shutdown = (signal) => {
|
|
10382
10382
|
if (shuttingDown) return;
|
package/dist/index.d.ts
CHANGED
|
@@ -196,6 +196,16 @@ declare function createServer(opts: {
|
|
|
196
196
|
db: DatabaseClient;
|
|
197
197
|
open?: boolean;
|
|
198
198
|
logger?: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* The network interface the server will bind to (from `canonry serve`).
|
|
201
|
+
* Used to gate the unauthenticated first-run dashboard password setup: on a
|
|
202
|
+
* loopback bind only local processes can reach `/session/setup`, so claiming
|
|
203
|
+
* the initial password without the API key is safe. On a non-loopback bind
|
|
204
|
+
* (`0.0.0.0`, a LAN IP) the setup endpoint additionally requires a valid
|
|
205
|
+
* bearer key so a remote first-visitor cannot mint a full-access session.
|
|
206
|
+
* Defaults to loopback when unset (programmatic/test callers).
|
|
207
|
+
*/
|
|
208
|
+
host?: string;
|
|
199
209
|
}): Promise<FastifyInstance>;
|
|
200
210
|
|
|
201
211
|
export { type CanonryConfig, createServer, loadConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QY5WZWU4.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-WFMEK34V.js";
|
|
7
|
+
import "./chunk-JUWU2DV6.js";
|
|
8
|
+
import "./chunk-JNAKRK77.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
|
11
11
|
loadConfig
|
package/dist/mcp.js
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
PACKAGE_VERSION,
|
|
4
4
|
canonryMcpTools,
|
|
5
5
|
createApiClient
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-WFMEK34V.js";
|
|
7
|
+
import "./chunk-JNAKRK77.js";
|
|
8
8
|
|
|
9
9
|
// src/mcp/cli.ts
|
|
10
10
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.76.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -62,21 +62,21 @@
|
|
|
62
62
|
"@types/node-cron": "^3.0.11",
|
|
63
63
|
"tsup": "^8.5.1",
|
|
64
64
|
"tsx": "^4.19.0",
|
|
65
|
+
"@ainyc/canonry-api-client": "0.0.0",
|
|
65
66
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
67
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
66
68
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
67
|
-
"@ainyc/canonry-db": "0.0.0",
|
|
68
69
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
69
70
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
70
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
71
|
-
"@ainyc/canonry-integration-google": "0.0.0",
|
|
72
71
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
72
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
73
73
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
74
|
+
"@ainyc/canonry-db": "0.0.0",
|
|
75
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
74
76
|
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
75
77
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
76
|
-
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
77
|
-
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
78
78
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
79
|
-
"@ainyc/canonry-
|
|
79
|
+
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
80
80
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
81
81
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
82
82
|
"@ainyc/canonry-provider-local": "0.0.0",
|