@canonry/canonry 4.158.0 → 4.160.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 (53) hide show
  1. package/README.md +3 -3
  2. package/THIRD_PARTY_NOTICES.md +102 -0
  3. package/assets/THIRD_PARTY_NOTICES.md +102 -0
  4. package/assets/agent-workspace/skills/aero/SKILL.md +16 -1
  5. package/assets/agent-workspace/skills/canonry/SKILL.md +17 -5
  6. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +67 -0
  7. package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +231 -62
  8. package/assets/assets/{AuditHistoryPanel-McQfjoU9.js → AuditHistoryPanel-AtgoG2AH.js} +1 -1
  9. package/assets/assets/{BacklinksPage-Da8y1Wv8.js → BacklinksPage-DrOSF7Mu.js} +1 -1
  10. package/assets/assets/{HistoryPage-9MJfhRyT.js → HistoryPage-CGQXleJc.js} +1 -1
  11. package/assets/assets/{MeasurementPropertyPage-BiNAHEJW.js → MeasurementPropertyPage-C7D2OgIQ.js} +1 -1
  12. package/assets/assets/ProjectPage-Lp1VjNvL.js +12 -0
  13. package/assets/assets/{RunRow-DCG2LBlS.js → RunRow-BdzKKODo.js} +1 -1
  14. package/assets/assets/{RunsPage-ByWA_FSk.js → RunsPage-BU96L07S.js} +1 -1
  15. package/assets/assets/{SettingsPage-DdSeKAKF.js → SettingsPage-LEca0kDH.js} +1 -1
  16. package/assets/assets/SiteHealthSection-CKM4DUfE.js +4 -0
  17. package/assets/assets/{TrafficPage-5u8rPcBt.js → TrafficPage-tU9wl1F_.js} +1 -1
  18. package/assets/assets/{TrafficSourceDetailPage-Dm-fK87u.js → TrafficSourceDetailPage-DZTpnU9f.js} +1 -1
  19. package/assets/assets/extract-error-message-BAyN-ftk.js +1 -0
  20. package/assets/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  21. package/assets/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  22. package/assets/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  23. package/assets/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  24. package/assets/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
  25. package/assets/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
  26. package/assets/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
  27. package/assets/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
  28. package/assets/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
  29. package/assets/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
  30. package/assets/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  31. package/assets/assets/index-CACRaOmZ.css +1 -0
  32. package/assets/assets/index-Wqv7kvs-.js +83 -0
  33. package/assets/assets/{react-sigma_core.esm.min-ComIyDKi.js → react-sigma_core.esm.min-DlZOAc_w.js} +2 -2
  34. package/assets/assets/{vendor-lucide-BtYdosYk.js → vendor-lucide-nYKv-BB7.js} +1 -1
  35. package/assets/assets/{vendor-markdown-D274_wsI.js → vendor-markdown-Bn7fRwrx.js} +1 -1
  36. package/assets/assets/{vendor-radix-BxMXSwbC.js → vendor-radix-4UOaVWza.js} +1 -1
  37. package/assets/assets/{vendor-recharts-C4ktw_aE.js → vendor-recharts-D8rt5lKn.js} +1 -1
  38. package/assets/assets/{vendor-tanstack-pFxw0eGP.js → vendor-tanstack-Dock0eH1.js} +1 -1
  39. package/assets/index.html +7 -7
  40. package/dist/{chunk-DEVAEC2S.js → chunk-7M7T5QXS.js} +290 -16
  41. package/dist/{chunk-LK6YFHG4.js → chunk-HQAVEK42.js} +65 -15
  42. package/dist/{chunk-YP4K2KXH.js → chunk-X7CYY5Q7.js} +2687 -686
  43. package/dist/{chunk-4VZP64GZ.js → chunk-XGESWHFP.js} +660 -274
  44. package/dist/cli.js +333 -117
  45. package/dist/index.d.ts +37 -14
  46. package/dist/index.js +4 -4
  47. package/dist/{intelligence-service-LQ6ZRWMF.js → intelligence-service-6XQMM466.js} +2 -2
  48. package/dist/mcp.js +2 -2
  49. package/package.json +11 -9
  50. package/assets/assets/ProjectPage-mWSMjXrR.js +0 -15
  51. package/assets/assets/extract-error-message-CtxkAd6E.js +0 -1
  52. package/assets/assets/index-DUfg50Pl.js +0 -83
  53. package/assets/assets/index-cXb3mfeQ.css +0 -1
package/assets/index.html CHANGED
@@ -12,14 +12,14 @@
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-DUfg50Pl.js"></script>
16
- <link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-pFxw0eGP.js">
17
- <link rel="modulepreload" crossorigin href="./assets/vendor-radix-BxMXSwbC.js">
18
- <link rel="modulepreload" crossorigin href="./assets/vendor-recharts-C4ktw_aE.js">
19
- <link rel="modulepreload" crossorigin href="./assets/vendor-lucide-BtYdosYk.js">
20
- <link rel="modulepreload" crossorigin href="./assets/vendor-markdown-D274_wsI.js">
15
+ <script type="module" crossorigin src="./assets/index-Wqv7kvs-.js"></script>
16
+ <link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Dock0eH1.js">
17
+ <link rel="modulepreload" crossorigin href="./assets/vendor-radix-4UOaVWza.js">
18
+ <link rel="modulepreload" crossorigin href="./assets/vendor-recharts-D8rt5lKn.js">
19
+ <link rel="modulepreload" crossorigin href="./assets/vendor-lucide-nYKv-BB7.js">
20
+ <link rel="modulepreload" crossorigin href="./assets/vendor-markdown-Bn7fRwrx.js">
21
21
  <link rel="modulepreload" crossorigin href="./assets/vendor-yaml-GWJz5H2G.js">
22
- <link rel="stylesheet" crossorigin href="./assets/index-cXb3mfeQ.css">
22
+ <link rel="stylesheet" crossorigin href="./assets/index-CACRaOmZ.css">
23
23
  </head>
24
24
  <body>
25
25
  <div id="root"></div>
@@ -3518,6 +3518,12 @@ var projectUpsertRequestSchema = z3.object({
3518
3518
  autoExtractBacklinks: z3.boolean().optional(),
3519
3519
  configSource: configSourceSchema.optional()
3520
3520
  });
3521
+ var projectCreateRequestSchema = projectUpsertRequestSchema.extend({
3522
+ name: z3.string().trim().min(1).max(120)
3523
+ });
3524
+ function normalizeProjectName(input) {
3525
+ return input.trim().normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
3526
+ }
3521
3527
  var projectDtoSchema = z3.object({
3522
3528
  id: z3.string(),
3523
3529
  name: z3.string(),
@@ -5428,6 +5434,7 @@ var auditLogEntrySchema = z8.object({
5428
5434
  // ../contracts/src/scopes.ts
5429
5435
  var READ_ONLY_SCOPE = "read";
5430
5436
  var WILDCARD_SCOPE = "*";
5437
+ var PROJECTS_WRITE_SCOPE = "projects.write";
5431
5438
  var ADS_WRITE_SCOPE = "ads.write";
5432
5439
  var ADS_APPROVE_SCOPE = "ads.approve";
5433
5440
  var ADS_ACTIVATE_SCOPE = "ads.activate";
@@ -8486,7 +8493,7 @@ var siteAuditScoreSchema = z24.object({
8486
8493
  pagesErrored: z24.number().int().nonnegative(),
8487
8494
  /** `aggregateScore - previousScore`, or `null` when there is no prior run. */
8488
8495
  deltaScore: z24.number().nullable(),
8489
- trend: siteAuditTrendDirectionSchema.nullable(),
8496
+ trend: z24.union([siteAuditTrendDirectionSchema, z24.null()]),
8490
8497
  previousScore: z24.number().nullable(),
8491
8498
  previousAuditedAt: z24.string().nullable(),
8492
8499
  factors: z24.array(siteAuditFactorSummarySchema).default([]),
@@ -8577,8 +8584,21 @@ var siteCrawlTerminationSchema = z24.enum([
8577
8584
  "max-sitemap-urls",
8578
8585
  "root-host-redirect"
8579
8586
  ]);
8580
- var siteHealthStateSchema = z24.enum(["eligible", "hidden", "failed", "unchecked"]);
8587
+ function isSelfLink(sourceUrl, targetUrl) {
8588
+ return sourceUrl === targetUrl;
8589
+ }
8590
+ var siteHealthStateSchema = z24.enum([
8591
+ "eligible",
8592
+ "hidden",
8593
+ /** Fetched, but not an HTML page: a text file, a PDF, an image. Not a fault. */
8594
+ "resource",
8595
+ /** Fetched and redirected elsewhere. Moved, not hidden. */
8596
+ "redirect",
8597
+ "failed",
8598
+ "unchecked"
8599
+ ]);
8581
8600
  var SiteHealthStates = siteHealthStateSchema.enum;
8601
+ var SITE_GRAPH_LEGEND_STATES = siteHealthStateSchema.options;
8582
8602
  var SiteCrawlFetchStates = {
8583
8603
  discovered: "discovered",
8584
8604
  robotsBlocked: "robots-blocked",
@@ -8616,9 +8636,16 @@ function deriveSiteHealthState(input) {
8616
8636
  return "failed";
8617
8637
  case SiteCrawlFetchStates.discovered:
8618
8638
  return "unchecked";
8639
+ // A non-HTML resource was fetched successfully. It is simply not a page,
8640
+ // which is a fact about its type, not a problem with the site.
8641
+ case SiteCrawlFetchStates.nonHtml:
8642
+ return "resource";
8643
+ // A redirect moved; nothing about it says "do not index me".
8619
8644
  case SiteCrawlFetchStates.redirect:
8645
+ return "redirect";
8646
+ // robots.txt IS the site telling engines not to fetch this, so it is the
8647
+ // one fetch state that genuinely belongs with the hidden pages.
8620
8648
  case SiteCrawlFetchStates.robotsBlocked:
8621
- case SiteCrawlFetchStates.nonHtml:
8622
8649
  return "hidden";
8623
8650
  case SiteCrawlFetchStates.html:
8624
8651
  break;
@@ -8637,6 +8664,56 @@ function deriveSiteHealthState(input) {
8637
8664
  return "unchecked";
8638
8665
  }
8639
8666
  }
8667
+ var TEMPLATE_LINK_RATIO_THRESHOLD = 0.7;
8668
+ var TEMPLATE_LINK_MIN_FETCHED_PAGES = 15;
8669
+ var siteHealthTemplateDetectionSchema = z24.enum([
8670
+ "applied",
8671
+ "unavailable-too-few-pages",
8672
+ "unavailable-legacy-scan"
8673
+ ]);
8674
+ var SiteHealthTemplateDetections = siteHealthTemplateDetectionSchema.enum;
8675
+ var siteHealthLinkKindSchema = z24.enum(["all", "content", "template"]);
8676
+ var SiteHealthLinkKinds = siteHealthLinkKindSchema.enum;
8677
+ function normalizeTemplateAnchorText(anchor) {
8678
+ return anchor.trim().replace(/\s+/gu, " ").toLowerCase();
8679
+ }
8680
+ function createTemplateLinkPairIndex() {
8681
+ return { sourcePagesByPair: /* @__PURE__ */ new Map() };
8682
+ }
8683
+ function templateLinkPairKey(targetNodeKey, normalizedAnchor) {
8684
+ return `${targetNodeKey}${normalizedAnchor}`;
8685
+ }
8686
+ function observeTemplateLinkEdges(index, edges) {
8687
+ for (const edge of edges) {
8688
+ if (edge.targetNodeKey == null) continue;
8689
+ for (const anchor of edge.anchors) {
8690
+ const key = templateLinkPairKey(edge.targetNodeKey, normalizeTemplateAnchorText(anchor));
8691
+ const sources = index.sourcePagesByPair.get(key);
8692
+ if (sources) sources.add(edge.sourceNodeKey);
8693
+ else index.sourcePagesByPair.set(key, /* @__PURE__ */ new Set([edge.sourceNodeKey]));
8694
+ }
8695
+ }
8696
+ }
8697
+ function templateLinkRatio(index, pagesFetched, edge) {
8698
+ if (edge.targetNodeKey == null || edge.anchors.length === 0) return null;
8699
+ if (!Number.isFinite(pagesFetched) || pagesFetched <= 0) return null;
8700
+ let least = null;
8701
+ for (const anchor of edge.anchors) {
8702
+ const sources = index.sourcePagesByPair.get(
8703
+ templateLinkPairKey(edge.targetNodeKey, normalizeTemplateAnchorText(anchor))
8704
+ );
8705
+ if (!sources) continue;
8706
+ const ratio = Math.min(1, sources.size / pagesFetched);
8707
+ if (least == null || ratio < least) least = ratio;
8708
+ }
8709
+ return least == null ? null : Math.round(least * 1e6) / 1e6;
8710
+ }
8711
+ function isTemplateLinkRatio(ratio) {
8712
+ return ratio != null && ratio >= TEMPLATE_LINK_RATIO_THRESHOLD;
8713
+ }
8714
+ function templateLinkDetection(pagesFetched) {
8715
+ return Number.isFinite(pagesFetched) && pagesFetched >= TEMPLATE_LINK_MIN_FETCHED_PAGES ? SiteHealthTemplateDetections.applied : SiteHealthTemplateDetections["unavailable-too-few-pages"];
8716
+ }
8640
8717
  var siteCrawlPageSchema = z24.object({
8641
8718
  nodeKey: z24.string(),
8642
8719
  url: z24.string(),
@@ -8714,12 +8791,15 @@ var siteCrawlPageAuditSchema = z24.discriminatedUnion("state", [
8714
8791
  criticalDefects: z24.array(siteCrawlCriticalDefectSchema).default([])
8715
8792
  })
8716
8793
  ]);
8794
+ var siteCrawlPagesFilterStateSchema = z24.enum(["applied", "unavailable-legacy-scan"]);
8717
8795
  var siteCrawlPagesResponseSchema = z24.object({
8718
8796
  project: z24.string(),
8719
8797
  hasCrawlData: z24.boolean(),
8720
8798
  runId: z24.string().nullable(),
8721
8799
  total: z24.number().int().nonnegative(),
8722
8800
  nextCursor: z24.string().nullable(),
8801
+ /** Null when no `healthState` filter was requested. */
8802
+ healthStateFilter: z24.union([siteCrawlPagesFilterStateSchema, z24.null()]).default(null),
8723
8803
  pages: z24.array(siteCrawlPageSchema).default([])
8724
8804
  });
8725
8805
  var siteCrawlStructureChildSchema = z24.object({
@@ -8751,7 +8831,19 @@ var siteCrawlEdgeSchema = z24.object({
8751
8831
  occurrences: z24.number().int().positive(),
8752
8832
  followableOccurrences: z24.number().int().nonnegative(),
8753
8833
  nofollowOccurrences: z24.number().int().nonnegative(),
8754
- anchors: z24.array(z24.string()).default([])
8834
+ anchors: z24.array(z24.string()).default([]),
8835
+ /**
8836
+ * True when this link repeats across the scan as nav, header, or footer
8837
+ * chrome. Null means the scan never classified its links, which the
8838
+ * response's `templateDetection` explains; it never means "not a nav link".
8839
+ */
8840
+ isTemplate: z24.union([z24.boolean(), z24.null()]),
8841
+ /**
8842
+ * Share of fetched pages carrying this link's LEAST ubiquitous anchor: the
8843
+ * most editorial thing anyone says when linking these two pages. At or above
8844
+ * the threshold means every anchor on the link is chrome.
8845
+ */
8846
+ templateRatio: z24.union([z24.number(), z24.null()])
8755
8847
  });
8756
8848
  var siteCrawlGraphNodeSchema = z24.object({
8757
8849
  nodeKey: z24.string(),
@@ -8777,7 +8869,13 @@ var siteCrawlGraphEdgeSchema = z24.object({
8777
8869
  sourceNodeKey: z24.string(),
8778
8870
  targetNodeKey: z24.string(),
8779
8871
  followable: z24.boolean(),
8780
- occurrences: z24.number().int().positive()
8872
+ occurrences: z24.number().int().positive(),
8873
+ /**
8874
+ * True for a nav, header, or footer link. Template links are published in
8875
+ * the sample so a viewer can switch them on without a refetch, but they were
8876
+ * excluded from the layout, so switching them on must never move a node.
8877
+ */
8878
+ isTemplate: z24.boolean()
8781
8879
  });
8782
8880
  var siteCrawlGraphLayoutUnavailableReasonSchema = z24.enum([
8783
8881
  "no-crawl",
@@ -8790,7 +8888,15 @@ var siteCrawlGraphLayoutSchema = z24.discriminatedUnion("state", [
8790
8888
  z24.object({
8791
8889
  state: z24.literal("ready"),
8792
8890
  version: z24.string().min(1),
8793
- computedAt: z24.string().min(1)
8891
+ computedAt: z24.string().min(1),
8892
+ /**
8893
+ * True when nav, header, and footer links were kept out of the physics, so
8894
+ * positions describe content structure. False for a scan published before
8895
+ * template detection: its links are classified by the migration backfill
8896
+ * and can still be filtered, but its node positions were computed with the
8897
+ * nav mesh included. Re-running the scan is what updates them.
8898
+ */
8899
+ templateLinksExcluded: z24.boolean()
8794
8900
  }),
8795
8901
  z24.object({
8796
8902
  state: z24.literal("unavailable"),
@@ -8810,10 +8916,22 @@ var siteCrawlGraphResponseSchema = z24.object({
8810
8916
  */
8811
8917
  rootNodeKey: z24.string().nullable(),
8812
8918
  layout: siteCrawlGraphLayoutSchema,
8919
+ /** Whether nav and footer links could be told apart for this scan. */
8920
+ templateDetection: siteHealthTemplateDetectionSchema,
8921
+ /** Echo of the requested `linkKind`, so a caller knows what `edges` holds. */
8922
+ linkKind: siteHealthLinkKindSchema,
8813
8923
  /** Total canonical pages in the persisted crawl before graph sampling. */
8814
8924
  totalNodes: z24.number().int().nonnegative(),
8815
- /** Total graph-compatible internal anchor edges before graph sampling. */
8925
+ /**
8926
+ * Total graph-compatible internal anchor edges before graph sampling. This
8927
+ * keeps counting EVERY link, whatever `linkKind` was requested, so the
8928
+ * content and template counts below split a number that never moved.
8929
+ */
8816
8930
  totalEdges: z24.number().int().nonnegative(),
8931
+ /** Share of `totalEdges` classified as nav, header, or footer links. */
8932
+ totalTemplateEdges: z24.number().int().nonnegative(),
8933
+ /** `totalEdges - totalTemplateEdges`. Equals `totalEdges` when detection is unavailable. */
8934
+ totalContentEdges: z24.number().int().nonnegative(),
8817
8935
  nodes: z24.array(siteCrawlGraphNodeSchema).default([]),
8818
8936
  edges: z24.array(siteCrawlGraphEdgeSchema).default([]),
8819
8937
  omittedNodes: z24.number().int().nonnegative(),
@@ -8959,8 +9077,13 @@ var siteCrawlInternalLinksResponseSchema = z24.object({
8959
9077
  project: z24.string(),
8960
9078
  hasCrawlData: z24.boolean(),
8961
9079
  runId: z24.string().nullable(),
9080
+ /** Total links matching every requested filter, `linkKind` included. */
8962
9081
  total: z24.number().int().nonnegative(),
8963
9082
  nextCursor: z24.string().nullable(),
9083
+ /** Whether nav and footer links could be told apart for this scan. */
9084
+ templateDetection: siteHealthTemplateDetectionSchema,
9085
+ /** Echo of the requested `linkKind`, so a caller knows what `total` counts. */
9086
+ linkKind: siteHealthLinkKindSchema,
8964
9087
  edges: z24.array(siteCrawlEdgeSchema).default([])
8965
9088
  });
8966
9089
  var siteCrawlNeighborsResponseSchema = z24.object({
@@ -8969,6 +9092,10 @@ var siteCrawlNeighborsResponseSchema = z24.object({
8969
9092
  runId: z24.string().nullable(),
8970
9093
  nodeKey: z24.string().nullable(),
8971
9094
  url: z24.string().nullable(),
9095
+ /** Whether nav and footer links could be told apart for this scan. */
9096
+ templateDetection: siteHealthTemplateDetectionSchema,
9097
+ /** Echo of the requested `linkKind`, so a caller knows what the lists hold. */
9098
+ linkKind: siteHealthLinkKindSchema,
8972
9099
  inbound: z24.array(siteCrawlEdgeSchema).default([]),
8973
9100
  outbound: z24.array(siteCrawlEdgeSchema).default([]),
8974
9101
  inboundTruncated: z24.boolean(),
@@ -9065,6 +9192,61 @@ var siteHealthScansResponseSchema = z24.object({
9065
9192
  });
9066
9193
  var SITE_HEALTH_SCANS_DEFAULT_LIMIT = 20;
9067
9194
  var SITE_HEALTH_SCANS_MAX_LIMIT = 100;
9195
+ var siteAuditRunPhaseSchema = z24.enum([
9196
+ "queued",
9197
+ "discovering",
9198
+ "checking",
9199
+ "arranging-map",
9200
+ "completed",
9201
+ "partial",
9202
+ "failed",
9203
+ "cancelled"
9204
+ ]);
9205
+ var siteAuditRunLayoutSchema = z24.object({
9206
+ state: z24.enum(["pending", "ready", "unavailable"]),
9207
+ layoutVersion: z24.string().nullable(),
9208
+ failureCode: z24.string().nullable(),
9209
+ updatedAt: z24.string().nullable()
9210
+ });
9211
+ var siteAuditRunAttemptProgressSchema = z24.object({
9212
+ id: z24.string(),
9213
+ state: z24.string(),
9214
+ pagesDiscovered: z24.number().int().nonnegative(),
9215
+ pagesFetched: z24.number().int().nonnegative(),
9216
+ pagesEligible: z24.number().int().nonnegative(),
9217
+ pagesErrored: z24.number().int().nonnegative(),
9218
+ edgesDiscovered: z24.number().int().nonnegative(),
9219
+ lastUpdatedAt: z24.string(),
9220
+ startedAt: z24.string().nullable(),
9221
+ finishedAt: z24.string().nullable(),
9222
+ error: z24.string().nullable()
9223
+ });
9224
+ var siteAuditRunProgressSchema = z24.object({
9225
+ project: z24.string(),
9226
+ runId: z24.string(),
9227
+ status: runStatusSchema,
9228
+ phase: siteAuditRunPhaseSchema,
9229
+ attempt: siteAuditRunAttemptProgressSchema.nullable(),
9230
+ layout: siteAuditRunLayoutSchema,
9231
+ error: z24.string().nullable()
9232
+ });
9233
+ var siteAuditLivePageHealthStateSchema = z24.enum(["waiting", "collecting", "terminal"]);
9234
+ var siteAuditLivePageHealthExampleSchema = z24.object({
9235
+ nodeKey: z24.string(),
9236
+ url: z24.string(),
9237
+ auditScore: z24.number(),
9238
+ checksNeedingAttention: z24.number().int().nonnegative()
9239
+ });
9240
+ var siteAuditLivePageHealthSchema = z24.object({
9241
+ project: z24.string(),
9242
+ runId: z24.string(),
9243
+ status: runStatusSchema,
9244
+ state: siteAuditLivePageHealthStateSchema,
9245
+ attemptId: z24.string().nullable(),
9246
+ pagesAudited: z24.number().int().nonnegative(),
9247
+ updatedAt: z24.string().nullable(),
9248
+ examples: z24.array(siteAuditLivePageHealthExampleSchema).max(12).default([])
9249
+ });
9068
9250
 
9069
9251
  // ../contracts/src/schedule.ts
9070
9252
  import { z as z25 } from "zod";
@@ -12759,6 +12941,10 @@ var trafficSourceDtoSchema = z44.object({
12759
12941
  * the skipping sync did.
12760
12942
  */
12761
12943
  skippedThroughAt: z44.string().nullable(),
12944
+ /** Residual Cloudflare Queue depth reported by the most recent bounded pull. */
12945
+ queueBacklogCount: z44.number().int().nonnegative().nullable(),
12946
+ /** Instant at which `queueBacklogCount` was observed, or null before the first pull. */
12947
+ queueBacklogObservedAt: z44.string().nullable(),
12762
12948
  archivedAt: z44.string().nullable(),
12763
12949
  config: z44.record(z44.string(), z44.unknown()),
12764
12950
  createdAt: z44.string(),
@@ -12792,34 +12978,96 @@ var trafficConnectVercelRequestSchema = z44.object({
12792
12978
  });
12793
12979
  var cloudflareTrafficDeliveryModeSchema = z44.enum(["direct-push", "queue-pull"]);
12794
12980
  var CloudflareTrafficDeliveryModes = cloudflareTrafficDeliveryModeSchema.enum;
12795
- var cloudflareTrafficSourceConfigSchema = z44.object({
12981
+ var cloudflareQueueNameSchema = z44.string().regex(
12982
+ /^(?=.{1,63}$)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
12983
+ "Cloudflare Queue name must be 1-63 characters, use only letters, numbers, or dashes, and start and end with a letter or number"
12984
+ );
12985
+ var cloudflareTrafficSourceBaseSchema = z44.object({
12796
12986
  schemaVersion: z44.literal(1),
12797
- deliveryMode: z44.literal(CloudflareTrafficDeliveryModes["direct-push"]).default("direct-push"),
12798
12987
  /** Semver of the Worker script bundle that was generated at connect/rotate time. */
12799
12988
  workerVersion: z44.string().min(1),
12800
12989
  /** Identifier of the bot/referer keyword set baked into the deployed Worker. */
12801
12990
  expectedBotListVersion: z44.string().min(1),
12802
12991
  /** Target Cloudflare zone for the operator-managed Worker route. */
12803
- zoneId: z44.string().nullable(),
12992
+ zoneId: z44.string().nullable()
12993
+ });
12994
+ var cloudflareDirectPushTrafficSourceConfigSchema = cloudflareTrafficSourceBaseSchema.extend({
12995
+ deliveryMode: z44.literal(CloudflareTrafficDeliveryModes["direct-push"]),
12804
12996
  /** Cloudflare account id used to target the correct account during Wrangler deploy. */
12805
12997
  accountId: z44.string().nullable()
12806
12998
  });
12807
- var trafficConnectCloudflareRequestSchema = z44.object({
12808
- deliveryMode: z44.literal(CloudflareTrafficDeliveryModes["direct-push"]).default("direct-push"),
12999
+ var cloudflareQueuePullTrafficSourceConfigSchema = cloudflareTrafficSourceBaseSchema.extend({
13000
+ deliveryMode: z44.literal(CloudflareTrafficDeliveryModes["queue-pull"]),
13001
+ /** Cloudflare account that owns the Queue. */
13002
+ accountId: z44.string().min(1),
13003
+ /** Cloudflare Queue id used by Canonry's pull consumer. */
13004
+ queueId: z44.string().min(1),
13005
+ /** Queue producer binding target written to the generated Wrangler file. */
13006
+ queueName: cloudflareQueueNameSchema,
13007
+ /** Operator-recorded Queue retention for configuration drift checks. */
13008
+ retentionSeconds: z44.number().int().min(60).max(1209600)
13009
+ });
13010
+ function defaultCloudflareDeliveryMode(value) {
13011
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return value;
13012
+ const record = value;
13013
+ return "deliveryMode" in record ? value : { ...record, deliveryMode: "direct-push" };
13014
+ }
13015
+ var cloudflareTrafficSourceConfigSchema = z44.preprocess(
13016
+ defaultCloudflareDeliveryMode,
13017
+ z44.discriminatedUnion("deliveryMode", [
13018
+ cloudflareDirectPushTrafficSourceConfigSchema,
13019
+ cloudflareQueuePullTrafficSourceConfigSchema
13020
+ ])
13021
+ );
13022
+ var trafficConnectCloudflareBaseRequestSchema = z44.object({
12809
13023
  displayName: z44.string().min(1).optional(),
12810
13024
  /** Target Cloudflare zone. Canonry does not validate it against Cloudflare. */
12811
- zoneId: z44.string().min(1).optional(),
13025
+ zoneId: z44.string().min(1).optional()
13026
+ });
13027
+ var trafficConnectCloudflareDirectPushRequestSchema = trafficConnectCloudflareBaseRequestSchema.extend({
13028
+ deliveryMode: z44.literal(CloudflareTrafficDeliveryModes["direct-push"]),
12812
13029
  /** Cloudflare account id. Set it when Wrangler can access more than one account. */
12813
13030
  accountId: z44.string().min(1).optional()
12814
13031
  });
12815
- var trafficConnectCloudflareResponseSchema = z44.object({
13032
+ var trafficConnectCloudflareQueuePullRequestSchema = trafficConnectCloudflareBaseRequestSchema.extend({
13033
+ deliveryMode: z44.literal(CloudflareTrafficDeliveryModes["queue-pull"]),
13034
+ accountId: z44.string().min(1),
13035
+ queueId: z44.string().min(1),
13036
+ queueName: cloudflareQueueNameSchema,
13037
+ retentionSeconds: z44.number().int().min(60).max(1209600),
13038
+ /** Queue pull token; secret-store only, never persisted in configJson or returned. */
13039
+ apiToken: z44.string().min(1)
13040
+ });
13041
+ var trafficConnectCloudflareRequestSchema = z44.preprocess(
13042
+ defaultCloudflareDeliveryMode,
13043
+ z44.discriminatedUnion("deliveryMode", [
13044
+ trafficConnectCloudflareDirectPushRequestSchema,
13045
+ trafficConnectCloudflareQueuePullRequestSchema
13046
+ ])
13047
+ );
13048
+ var trafficConnectCloudflareResponseBaseSchema = z44.object({
12816
13049
  sourceId: z44.string().min(1),
12817
- deliveryMode: z44.literal(CloudflareTrafficDeliveryModes["direct-push"]),
12818
13050
  workerScript: z44.string().min(1),
12819
13051
  wranglerToml: z44.string().min(1),
12820
13052
  workerVersion: z44.string().min(1),
12821
13053
  instructions: z44.string().min(1)
12822
13054
  });
13055
+ var trafficConnectCloudflareDirectPushResponseSchema = trafficConnectCloudflareResponseBaseSchema.extend({
13056
+ deliveryMode: z44.literal(CloudflareTrafficDeliveryModes["direct-push"]),
13057
+ activationRequired: z44.boolean().default(false)
13058
+ });
13059
+ var trafficConnectCloudflareQueuePullResponseSchema = trafficConnectCloudflareResponseBaseSchema.extend({
13060
+ deliveryMode: z44.literal(CloudflareTrafficDeliveryModes["queue-pull"]),
13061
+ activationRequired: z44.boolean().default(false),
13062
+ accountId: z44.string().min(1),
13063
+ queueId: z44.string().min(1),
13064
+ queueName: cloudflareQueueNameSchema,
13065
+ retentionSeconds: z44.number().int().min(60).max(1209600)
13066
+ });
13067
+ var trafficConnectCloudflareResponseSchema = z44.discriminatedUnion("deliveryMode", [
13068
+ trafficConnectCloudflareDirectPushResponseSchema,
13069
+ trafficConnectCloudflareQueuePullResponseSchema
13070
+ ]);
12823
13071
  var cloudflareEdgeEventSchema = z44.object({
12824
13072
  /** Cloudflare `cf-ray` request id — globally unique per request. */
12825
13073
  eventId: z44.string().min(1),
@@ -12870,6 +13118,8 @@ var trafficSyncResponseSchema = z44.object({
12870
13118
  aiUserFetchBucketRows: z44.number().int().nonnegative(),
12871
13119
  aiReferralBucketRows: z44.number().int().nonnegative(),
12872
13120
  sampleRows: z44.number().int().nonnegative(),
13121
+ /** Residual upstream Queue depth after a bounded sync; present for Queue pull. */
13122
+ remainingBacklogCount: z44.number().int().nonnegative().optional(),
12873
13123
  windowStart: z44.string(),
12874
13124
  windowEnd: z44.string()
12875
13125
  });
@@ -14280,9 +14530,15 @@ function buildEmbedClientConfig(resolved) {
14280
14530
  const client = { enabled: true };
14281
14531
  if (resolved.views && resolved.views.length > 0) client.views = resolved.views;
14282
14532
  if (resolved.projectTabs && resolved.projectTabs.length > 0) client.projectTabs = resolved.projectTabs;
14283
- if (resolved.theme && Object.keys(resolved.theme).length > 0) client.theme = resolved.theme;
14533
+ const theme = withoutFontOverride(resolved.theme);
14534
+ if (theme) client.theme = theme;
14284
14535
  return client;
14285
14536
  }
14537
+ function withoutFontOverride(theme) {
14538
+ if (!theme) return void 0;
14539
+ const entries = Object.entries(theme).filter(([key]) => key.toLowerCase() !== "font");
14540
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
14541
+ }
14286
14542
  function normalizeIdTokens(raw) {
14287
14543
  if (raw.length === 0) return void 0;
14288
14544
  const seen = /* @__PURE__ */ new Set();
@@ -14309,6 +14565,7 @@ function parseThemeOverride(raw) {
14309
14565
  for (const [k, v] of Object.entries(parsed)) {
14310
14566
  if (Object.keys(out).length >= 12) break;
14311
14567
  if (typeof k !== "string" || k.length === 0 || k.length > 32) continue;
14568
+ if (k.toLowerCase() === "font") continue;
14312
14569
  if (typeof v !== "string" || v.length > 256) continue;
14313
14570
  out[k] = v;
14314
14571
  }
@@ -14497,6 +14754,8 @@ export {
14497
14754
  orderLocationsDefaultFirst,
14498
14755
  resolveLocations,
14499
14756
  projectUpsertRequestSchema,
14757
+ projectCreateRequestSchema,
14758
+ normalizeProjectName,
14500
14759
  projectDtoSchema,
14501
14760
  queryDtoSchema,
14502
14761
  keywordDtoSchema,
@@ -14744,9 +15003,20 @@ export {
14744
15003
  siteAuditPagesResponseSchema,
14745
15004
  siteAuditTrendResponseSchema,
14746
15005
  siteCrawlSummarySchema,
15006
+ isSelfLink,
14747
15007
  siteHealthStateSchema,
14748
15008
  SiteCrawlFetchedStates,
14749
15009
  deriveSiteHealthState,
15010
+ TEMPLATE_LINK_RATIO_THRESHOLD,
15011
+ siteHealthTemplateDetectionSchema,
15012
+ SiteHealthTemplateDetections,
15013
+ siteHealthLinkKindSchema,
15014
+ SiteHealthLinkKinds,
15015
+ createTemplateLinkPairIndex,
15016
+ observeTemplateLinkEdges,
15017
+ templateLinkRatio,
15018
+ isTemplateLinkRatio,
15019
+ templateLinkDetection,
14750
15020
  siteCrawlAuditFactorSchema,
14751
15021
  siteCrawlCriticalDefectSchema,
14752
15022
  siteCrawlPageAuditSchema,
@@ -14783,6 +15053,8 @@ export {
14783
15053
  siteHealthScansResponseSchema,
14784
15054
  SITE_HEALTH_SCANS_DEFAULT_LIMIT,
14785
15055
  SITE_HEALTH_SCANS_MAX_LIMIT,
15056
+ siteAuditRunProgressSchema,
15057
+ siteAuditLivePageHealthSchema,
14786
15058
  schedulableRunKindSchema,
14787
15059
  SchedulableRunKinds,
14788
15060
  scheduleDtoSchema,
@@ -14927,6 +15199,7 @@ export {
14927
15199
  trafficConnectWordpressRequestSchema,
14928
15200
  trafficConnectVercelRequestSchema,
14929
15201
  CloudflareTrafficDeliveryModes,
15202
+ cloudflareQueueNameSchema,
14930
15203
  cloudflareTrafficSourceConfigSchema,
14931
15204
  trafficConnectCloudflareRequestSchema,
14932
15205
  trafficConnectCloudflareResponseSchema,
@@ -15022,6 +15295,7 @@ export {
15022
15295
  escapeLikePattern,
15023
15296
  READ_ONLY_SCOPE,
15024
15297
  WILDCARD_SCOPE,
15298
+ PROJECTS_WRITE_SCOPE,
15025
15299
  ADS_WRITE_SCOPE,
15026
15300
  ADS_APPROVE_SCOPE,
15027
15301
  ADS_ACTIVATE_SCOPE,