@ainyc/canonry 4.112.7 → 4.114.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 (28) hide show
  1. package/assets/assets/{BacklinksPage-AYTE7he1.js → BacklinksPage-pxm5QdkH.js} +1 -1
  2. package/assets/assets/{ChartPrimitives-J0xH87kk.js → ChartPrimitives-lKnj_JyP.js} +1 -1
  3. package/assets/assets/ProjectPage-38ZIpkmq.js +7 -0
  4. package/assets/assets/{RunRow-Duz6GoZ0.js → RunRow-BCinrp7o.js} +1 -1
  5. package/assets/assets/{RunsPage-DpocjSZ-.js → RunsPage-CRoqsHH6.js} +1 -1
  6. package/assets/assets/SettingsPage-BEJ39Z1y.js +1 -0
  7. package/assets/assets/{TrafficPage-B5c8opWF.js → TrafficPage-DwlIys8k.js} +1 -1
  8. package/assets/assets/{TrafficSourceDetailPage-D9JPwzH-.js → TrafficSourceDetailPage-BxZdMbPs.js} +1 -1
  9. package/assets/assets/{arrow-left-DMukIffh.js → arrow-left-Bh1K7Q5q.js} +1 -1
  10. package/assets/assets/{extract-error-message-CVln-Uf_.js → extract-error-message-CC-RB1fH.js} +1 -1
  11. package/assets/assets/index--YS3kkht.js +210 -0
  12. package/assets/assets/index-CReX5Jn9.css +1 -0
  13. package/assets/assets/{trash-2-BbhOWhnf.js → trash-2-uW1qyzpW.js} +1 -1
  14. package/assets/index.html +2 -2
  15. package/dist/{chunk-D5PEINWZ.js → chunk-3VSTTH4M.js} +303 -185
  16. package/dist/{chunk-K2XOEBSH.js → chunk-DUBZH5JW.js} +1 -1
  17. package/dist/{chunk-DBZLOLYT.js → chunk-VEUBAZRG.js} +8 -1
  18. package/dist/{chunk-FVELOZTK.js → chunk-WMWZW34J.js} +71 -9
  19. package/dist/cli.js +4 -4
  20. package/dist/index.d.ts +9 -0
  21. package/dist/index.js +4 -4
  22. package/dist/{intelligence-service-ZPY7NIKR.js → intelligence-service-I5EQ77KZ.js} +2 -2
  23. package/dist/mcp.js +2 -2
  24. package/package.json +9 -9
  25. package/assets/assets/ProjectPage-BcqfsS5X.js +0 -7
  26. package/assets/assets/SettingsPage-CboDfSRx.js +0 -1
  27. package/assets/assets/index-DNoISJxr.js +0 -210
  28. package/assets/assets/index-l-PAIV0A.css +0 -1
@@ -25,7 +25,7 @@ import {
25
25
  trafficConnectVercelRequestSchema,
26
26
  trafficConnectWordpressRequestSchema,
27
27
  trafficEventKindSchema
28
- } from "./chunk-DBZLOLYT.js";
28
+ } from "./chunk-VEUBAZRG.js";
29
29
 
30
30
  // src/config.ts
31
31
  import fs from "fs";
@@ -5619,14 +5619,21 @@ function parseThemeOverride(raw) {
5619
5619
  }
5620
5620
  return Object.keys(out).length > 0 ? out : void 0;
5621
5621
  }
5622
- function embedClientConfigForRequest(resolved, projectTabsOverride, themeOverride) {
5622
+ function parseRenderTokenOverride(raw) {
5623
+ const value = Array.isArray(raw) ? raw[0] : raw;
5624
+ if (typeof value !== "string" || value.length === 0 || value.length > 4096) return void 0;
5625
+ return value;
5626
+ }
5627
+ function embedClientConfigForRequest(resolved, projectTabsOverride, themeOverride, renderTokenOverride) {
5623
5628
  const base = buildEmbedClientConfig(resolved);
5624
5629
  if (!base) return void 0;
5625
5630
  const tabs = normalizeIdTokens(splitList(projectTabsOverride));
5626
5631
  const theme = parseThemeOverride(themeOverride);
5632
+ const renderToken = parseRenderTokenOverride(renderTokenOverride);
5627
5633
  let out = base;
5628
5634
  if (tabs) out = { ...out, projectTabs: tabs };
5629
5635
  if (theme) out = { ...out, theme };
5636
+ if (renderToken) out = { ...out, renderToken };
5630
5637
  return out;
5631
5638
  }
5632
5639
  function serializeForInlineScript(value) {
@@ -10,7 +10,7 @@ import {
10
10
  loadConfig,
11
11
  loadConfigRaw,
12
12
  saveConfigPatch
13
- } from "./chunk-K2XOEBSH.js";
13
+ } from "./chunk-DUBZH5JW.js";
14
14
  import {
15
15
  CC_CACHE_DIR,
16
16
  DUCKDB_SPEC,
@@ -115,7 +115,7 @@ import {
115
115
  siteAuditPages,
116
116
  siteAuditSnapshots,
117
117
  usageCounters
118
- } from "./chunk-D5PEINWZ.js";
118
+ } from "./chunk-3VSTTH4M.js";
119
119
  import {
120
120
  AGENT_MEMORY_VALUE_MAX_BYTES,
121
121
  AGENT_PROVIDER_IDS,
@@ -178,7 +178,7 @@ import {
178
178
  validationError,
179
179
  winnabilityClassLabel,
180
180
  withRetry
181
- } from "./chunk-DBZLOLYT.js";
181
+ } from "./chunk-VEUBAZRG.js";
182
182
 
183
183
  // src/telemetry.ts
184
184
  import crypto from "crypto";
@@ -2752,6 +2752,13 @@ var perplexityAdapter = {
2752
2752
  };
2753
2753
 
2754
2754
  // src/embed.ts
2755
+ var DEFAULT_EMBED_PROJECT_TABS = ["overview"];
2756
+ var SERVER_ENFORCED_EMBED_PROJECT_TABS = ["overview", "technical-aeo", "report"];
2757
+ function unsupportedEmbedProjectTabs(projectTabs) {
2758
+ if (!projectTabs) return [];
2759
+ const supported = new Set(SERVER_ENFORCED_EMBED_PROJECT_TABS);
2760
+ return projectTabs.filter((tab) => !supported.has(tab));
2761
+ }
2755
2762
  function resolveEmbedConfig(env, config) {
2756
2763
  const embed = config.embed;
2757
2764
  const rawEnabled = env.CANONRY_EMBED?.trim();
@@ -2760,7 +2767,7 @@ function resolveEmbedConfig(env, config) {
2760
2767
  const rawViews = env.CANONRY_EMBED_VIEWS !== void 0 ? splitList(env.CANONRY_EMBED_VIEWS) : splitList(embed?.views);
2761
2768
  const views = normalizeIdTokens(rawViews);
2762
2769
  const rawProjectTabs = env.CANONRY_EMBED_PROJECT_TABS !== void 0 ? splitList(env.CANONRY_EMBED_PROJECT_TABS) : splitList(embed?.projectTabs);
2763
- const projectTabs = normalizeIdTokens(rawProjectTabs);
2770
+ const projectTabs = normalizeIdTokens(rawProjectTabs) ?? (enabled ? DEFAULT_EMBED_PROJECT_TABS : void 0);
2764
2771
  return {
2765
2772
  enabled,
2766
2773
  allowedOrigins,
@@ -6508,7 +6515,7 @@ function readStoredGroundingSources(rawResponse) {
6508
6515
  return result;
6509
6516
  }
6510
6517
  async function backfillInsightsCommand(project, opts) {
6511
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-ZPY7NIKR.js");
6518
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-I5EQ77KZ.js");
6512
6519
  const config = loadConfig();
6513
6520
  const db = createClient(config.database);
6514
6521
  migrate(db);
@@ -11004,6 +11011,16 @@ var DEFAULT_QUOTA = {
11004
11011
  };
11005
11012
  var SESSION_COOKIE_NAME = "canonry_session";
11006
11013
  var SESSION_TTL_MS = 12 * 60 * 60 * 1e3;
11014
+ function parseBooleanEnv(value) {
11015
+ const normalized = value?.trim().toLowerCase();
11016
+ if (!normalized) return void 0;
11017
+ if (normalized === "1" || normalized === "true" || normalized === "yes") return true;
11018
+ if (normalized === "0" || normalized === "false" || normalized === "no") return false;
11019
+ return void 0;
11020
+ }
11021
+ function resolveDashboardRequirePassword(env, config) {
11022
+ return parseBooleanEnv(env.CANONRY_DASHBOARD_REQUIRE_PASSWORD) ?? config.dashboard?.requirePassword ?? true;
11023
+ }
11007
11024
  var API_ADAPTERS = [
11008
11025
  geminiAdapter,
11009
11026
  openaiAdapter,
@@ -11164,6 +11181,24 @@ function isLoopbackBindHost(host) {
11164
11181
  if (/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(normalized)) return true;
11165
11182
  return false;
11166
11183
  }
11184
+ function resolveGooglePublicUrl(config, basePath) {
11185
+ const configured = config.publicUrl?.trim();
11186
+ if (configured) return configured;
11187
+ try {
11188
+ const url = new URL(config.apiUrl);
11189
+ if (url.protocol !== "http:" && url.protocol !== "https:") return void 0;
11190
+ if (!isLoopbackBindHost(url.hostname)) return void 0;
11191
+ const port = config.port && config.port > 0 ? String(config.port) : url.port;
11192
+ if (port === "0") return void 0;
11193
+ const pathFromApiUrl = url.pathname && url.pathname !== "/" ? url.pathname.replace(/\/$/, "") : "";
11194
+ const pathFromBasePath = basePath ? basePath.replace(/\/$/, "") : "";
11195
+ const pathSuffix = pathFromApiUrl || pathFromBasePath;
11196
+ const portSuffix = port ? `:${port}` : "";
11197
+ return `${url.protocol}//localhost${portSuffix}${pathSuffix}`;
11198
+ } catch {
11199
+ return void 0;
11200
+ }
11201
+ }
11167
11202
  async function createServer(opts) {
11168
11203
  const logger = opts.logger === false ? false : process.stdout.isTTY ? {
11169
11204
  transport: {
@@ -11597,7 +11632,23 @@ async function createServer(opts) {
11597
11632
  const basePath = normalizedBasePath === "/" ? void 0 : normalizedBasePath;
11598
11633
  const embed = resolveEmbedConfig(process.env, opts.config);
11599
11634
  const embedCsp = embed.enabled ? frameAncestorsHeaderValue(embed.allowedOrigins) : void 0;
11635
+ const unsupportedProjectTabs = unsupportedEmbedProjectTabs(embed.projectTabs);
11636
+ if (embed.enabled && unsupportedProjectTabs.length > 0) {
11637
+ app.log.warn(
11638
+ {
11639
+ projectTabs: unsupportedProjectTabs,
11640
+ supportedProjectTabs: [...SERVER_ENFORCED_EMBED_PROJECT_TABS]
11641
+ },
11642
+ "Embed project tabs include unsupported values; API reads for those tabs will be blocked"
11643
+ );
11644
+ }
11645
+ const dashboardRequirePassword = resolveDashboardRequirePassword(process.env, opts.config);
11646
+ app.log.info(
11647
+ { dashboardRequirePassword },
11648
+ "Dashboard password gate resolved"
11649
+ );
11600
11650
  const apiPrefix = basePath ? `${basePath}api/v1` : "/api/v1";
11651
+ const googlePublicUrl = resolveGooglePublicUrl(opts.config, basePath);
11601
11652
  if (opts.config.apiKey) {
11602
11653
  const keyHash = hashApiKey(opts.config.apiKey);
11603
11654
  const existing = opts.db.select().from(apiKeys).where(eq20(apiKeys.keyHash, keyHash)).get();
@@ -11680,6 +11731,9 @@ async function createServer(opts) {
11680
11731
  return Boolean(key && !key.revokedAt);
11681
11732
  };
11682
11733
  app.get(apiPrefix + "/session", async (request, reply) => {
11734
+ if (!dashboardRequirePassword) {
11735
+ return reply.send({ authenticated: true, setupRequired: false });
11736
+ }
11683
11737
  const sessionId = parseCookies(request.headers.cookie)[SESSION_COOKIE_NAME];
11684
11738
  return reply.send({
11685
11739
  authenticated: Boolean(sessionId && resolveSessionApiKeyId(sessionId)),
@@ -11687,6 +11741,9 @@ async function createServer(opts) {
11687
11741
  });
11688
11742
  });
11689
11743
  app.post(apiPrefix + "/session/setup", async (request, reply) => {
11744
+ if (!dashboardRequirePassword) {
11745
+ return reply.send({ authenticated: true, setupRequired: false });
11746
+ }
11690
11747
  if (!boundToLoopback && !requestHasValidApiKey(request)) {
11691
11748
  const err = authRequired(
11692
11749
  "This server is network-reachable; setting the dashboard password requires a valid API key."
@@ -11711,6 +11768,9 @@ async function createServer(opts) {
11711
11768
  return reply.send({ authenticated: true });
11712
11769
  });
11713
11770
  app.post(apiPrefix + "/session", async (request, reply) => {
11771
+ if (!dashboardRequirePassword) {
11772
+ return reply.send({ authenticated: true, setupRequired: false });
11773
+ }
11714
11774
  const password = request.body?.password?.trim();
11715
11775
  const apiKey = request.body?.apiKey?.trim();
11716
11776
  if (password) {
@@ -11815,6 +11875,7 @@ async function createServer(opts) {
11815
11875
  skipAuth: false,
11816
11876
  sessionCookieName: SESSION_COOKIE_NAME,
11817
11877
  resolveSessionApiKeyId,
11878
+ ...embed.enabled && embed.projectTabs ? { embedProjectTabs: embed.projectTabs } : {},
11818
11879
  explainContentRecommendation,
11819
11880
  briefContentRecommendation,
11820
11881
  briefPromptVersion: RECOMMENDATION_BRIEF_PROMPT_VERSION,
@@ -11866,7 +11927,7 @@ async function createServer(opts) {
11866
11927
  getAgentProviderSummary: () => buildAgentProvidersResponse(opts.config).providers,
11867
11928
  googleConnectionStore,
11868
11929
  googleStateSecret,
11869
- publicUrl: opts.config.publicUrl,
11930
+ publicUrl: googlePublicUrl,
11870
11931
  onGscSyncRequested: (runId, projectId, syncOpts) => {
11871
11932
  const { clientId: googleClientId, clientSecret: googleClientSecret } = getGoogleAuthConfig(opts.config);
11872
11933
  if (!googleClientId || !googleClientSecret) {
@@ -12308,11 +12369,11 @@ async function createServer(opts) {
12308
12369
  const assetsDir = opts.assetsDir ?? path9.join(dirname, "..", "assets");
12309
12370
  if (fs8.existsSync(assetsDir)) {
12310
12371
  const indexPath = path9.join(assetsDir, "index.html");
12311
- const injectConfig = (html, projectTabsOverride, themeOverride) => {
12372
+ const injectConfig = (html, projectTabsOverride, themeOverride, renderTokenOverride) => {
12312
12373
  const clientConfig = {};
12313
12374
  if (basePath) clientConfig.basePath = basePath;
12314
12375
  if (embed.enabled) {
12315
- const embedClient = embedClientConfigForRequest(embed, projectTabsOverride, themeOverride);
12376
+ const embedClient = embedClientConfigForRequest(embed, projectTabsOverride, themeOverride, renderTokenOverride);
12316
12377
  if (embedClient) clientConfig.embed = embedClient;
12317
12378
  }
12318
12379
  const configScript = `<script>window.__CANONRY_CONFIG__=${serializeForInlineScript(clientConfig)}</script>`;
@@ -12326,7 +12387,8 @@ async function createServer(opts) {
12326
12387
  injectConfig(
12327
12388
  html,
12328
12389
  reply.request.headers["x-canonry-embed-tabs"],
12329
- reply.request.headers["x-canonry-embed-theme"]
12390
+ reply.request.headers["x-canonry-embed-theme"],
12391
+ reply.request.headers["x-canonry-embed-render-token"]
12330
12392
  )
12331
12393
  );
12332
12394
  };
package/dist/cli.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  setTelemetrySource,
30
30
  showFirstRunNotice,
31
31
  trackEvent
32
- } from "./chunk-FVELOZTK.js";
32
+ } from "./chunk-WMWZW34J.js";
33
33
  import {
34
34
  CliError,
35
35
  EXIT_SYSTEM_ERROR,
@@ -46,7 +46,7 @@ import {
46
46
  saveConfig,
47
47
  saveConfigPatch,
48
48
  usageError
49
- } from "./chunk-K2XOEBSH.js";
49
+ } from "./chunk-DUBZH5JW.js";
50
50
  import {
51
51
  apiKeys,
52
52
  createClient,
@@ -54,7 +54,7 @@ import {
54
54
  projects,
55
55
  queries,
56
56
  renderReportHtml
57
- } from "./chunk-D5PEINWZ.js";
57
+ } from "./chunk-3VSTTH4M.js";
58
58
  import {
59
59
  BacklinkSources,
60
60
  CcReleaseSyncStatuses,
@@ -80,7 +80,7 @@ import {
80
80
  providerQuotaPolicySchema,
81
81
  resolveProviderInput,
82
82
  winnabilityClassSchema
83
- } from "./chunk-DBZLOLYT.js";
83
+ } from "./chunk-VEUBAZRG.js";
84
84
 
85
85
  // src/cli.ts
86
86
  import { pathToFileURL } from "url";
package/dist/index.d.ts CHANGED
@@ -183,6 +183,14 @@ interface AgentConfigEntry {
183
183
  */
184
184
  mode?: 'disabled';
185
185
  }
186
+ interface DashboardConfigEntry {
187
+ /**
188
+ * Whether the browser dashboard requires Canonry's built-in password/session
189
+ * gate. Defaults to true. Set false only when an upstream layer enforces auth
190
+ * and the engine is not directly internet-reachable.
191
+ */
192
+ requirePassword?: boolean;
193
+ }
186
194
  /**
187
195
  * Google Places API config — supplemental rendered-listing data for GBP
188
196
  * lodging locations (#648). The API key authenticates Place Details calls
@@ -220,6 +228,7 @@ interface CanonryConfig {
220
228
  vercelTraffic?: VercelTrafficConfigEntry;
221
229
  openaiAds?: OpenAiAdsConfigEntry;
222
230
  dashboardPasswordHash?: string;
231
+ dashboard?: DashboardConfigEntry;
223
232
  telemetry?: boolean;
224
233
  anonymousId?: string;
225
234
  lastSeenVersion?: string;
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-FVELOZTK.js";
3
+ } from "./chunk-WMWZW34J.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-K2XOEBSH.js";
7
- import "./chunk-D5PEINWZ.js";
8
- import "./chunk-DBZLOLYT.js";
6
+ } from "./chunk-DUBZH5JW.js";
7
+ import "./chunk-3VSTTH4M.js";
8
+ import "./chunk-VEUBAZRG.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-D5PEINWZ.js";
4
- import "./chunk-DBZLOLYT.js";
3
+ } from "./chunk-3VSTTH4M.js";
4
+ import "./chunk-VEUBAZRG.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  PACKAGE_VERSION,
4
4
  canonryMcpTools,
5
5
  createApiClient
6
- } from "./chunk-K2XOEBSH.js";
6
+ } from "./chunk-DUBZH5JW.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-DBZLOLYT.js";
9
+ } from "./chunk-VEUBAZRG.js";
10
10
 
11
11
  // src/mcp/cli.ts
12
12
  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.112.7",
3
+ "version": "4.114.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",
@@ -65,27 +65,27 @@
65
65
  "@types/node-cron": "^3.0.11",
66
66
  "tsup": "^8.5.1",
67
67
  "tsx": "^4.19.0",
68
- "@ainyc/canonry-api-client": "0.0.0",
69
68
  "@ainyc/canonry-config": "0.0.0",
70
- "@ainyc/canonry-api-routes": "0.0.0",
71
69
  "@ainyc/canonry-contracts": "0.0.0",
70
+ "@ainyc/canonry-api-routes": "0.0.0",
72
71
  "@ainyc/canonry-db": "0.0.0",
72
+ "@ainyc/canonry-api-client": "0.0.0",
73
73
  "@ainyc/canonry-integration-bing": "0.0.0",
74
74
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
75
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
76
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
77
75
  "@ainyc/canonry-integration-google": "0.0.0",
78
76
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
79
- "@ainyc/canonry-integration-google-places": "0.0.0",
77
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
80
78
  "@ainyc/canonry-integration-traffic": "0.0.0",
79
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
80
+ "@ainyc/canonry-integration-google-places": "0.0.0",
81
81
  "@ainyc/canonry-integration-wordpress": "0.0.0",
82
+ "@ainyc/canonry-provider-cdp": "0.0.0",
82
83
  "@ainyc/canonry-intelligence": "0.0.0",
83
84
  "@ainyc/canonry-provider-gemini": "0.0.0",
84
- "@ainyc/canonry-provider-cdp": "0.0.0",
85
+ "@ainyc/canonry-provider-openai": "0.0.0",
85
86
  "@ainyc/canonry-provider-local": "0.0.0",
86
87
  "@ainyc/canonry-provider-claude": "0.0.0",
87
- "@ainyc/canonry-provider-perplexity": "0.0.0",
88
- "@ainyc/canonry-provider-openai": "0.0.0"
88
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
89
89
  },
90
90
  "scripts": {
91
91
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",