@canonry/canonry 7.87.0 → 7.87.2

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 (33) hide show
  1. package/assets/agent-workspace/skills/aero/references/ai-traffic-tracking.md +6 -1
  2. package/assets/agent-workspace/skills/canonry/references/ai-traffic-tracking.md +6 -1
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +5 -1
  4. package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +27 -11
  5. package/dist/{backfill-LIMS34H6.js → backfill-6AYHWEQX.js} +5 -5
  6. package/dist/{bootstrap-AZYQXBHN.js → bootstrap-27NOBWTP.js} +1 -1
  7. package/dist/{chunk-YKB67YKH.js → chunk-3FHBPJ5R.js} +2 -2
  8. package/dist/{chunk-EQGCGZZY.js → chunk-AI75KS7G.js} +2183 -2076
  9. package/dist/{chunk-O26FQ7RI.js → chunk-AYYZ4HKJ.js} +30 -0
  10. package/dist/{chunk-L5NMS7AU.js → chunk-BVJA3TV2.js} +3 -3
  11. package/dist/{chunk-D5V6YQXA.js → chunk-IE4D47JE.js} +4 -4
  12. package/dist/{chunk-OJKWT6U6.js → chunk-IVGVPPQT.js} +8 -8
  13. package/dist/{chunk-JGGDENAA.js → chunk-LYTBHEID.js} +31 -31
  14. package/dist/{chunk-VDYXB6SV.js → chunk-POMLL2OZ.js} +83 -12
  15. package/dist/{chunk-KOBOKZXF.js → chunk-T2MGGW6Y.js} +2 -2
  16. package/dist/{chunk-EJZHL67Y.js → chunk-TFB2S6TQ.js} +1 -1
  17. package/dist/{chunk-ITOK75B6.js → chunk-ZCNKGBIV.js} +2 -2
  18. package/dist/{chunk-G44S34CE.js → chunk-ZJVQ72VC.js} +1 -1
  19. package/dist/{cli-commands-J6KWSWIS.js → cli-commands-H7BFVUGC.js} +1 -1
  20. package/dist/cli.js +2 -2
  21. package/dist/{dashboard-5QMYF4ZP.js → dashboard-KT2ACPI5.js} +3 -3
  22. package/dist/{demo-KGQL5EJM.js → demo-LWSLULEZ.js} +1 -1
  23. package/dist/{demo-server-ERIR2T2N.js → demo-server-UENMDVMG.js} +5 -5
  24. package/dist/index.d.ts +202 -67
  25. package/dist/index.js +9 -9
  26. package/dist/{init-HOBW5K2Q.js → init-TF3OPCEC.js} +2 -2
  27. package/dist/{intelligence-service-2AH42Y4Q.js → intelligence-service-LEH5UVIC.js} +4 -4
  28. package/dist/{serve-WF5ZXWW6.js → serve-LLIUILD2.js} +10 -10
  29. package/dist/{session-HEDEP77R.js → session-2NQKSF2N.js} +5 -5
  30. package/dist/{src-SJYGA7NH.js → src-JQYZ2TP6.js} +3 -1
  31. package/dist/{tools-KYG67FBW.js → tools-UPJRW4DN.js} +4 -4
  32. package/dist/{traffic-B7Q4WPOV.js → traffic-GWBZKYR5.js} +1 -1
  33. package/package.json +1 -1
@@ -31,7 +31,12 @@ rarely. Report every step separately; never pool them.
31
31
 
32
32
  Server-side hits are requests and GA4 counts sessions, and each instrument
33
33
  misses some visits the other sees, so the two never match exactly. Compare
34
- their trend, not their totals.
34
+ their trend, not their totals. Server-side arrivals stored before Canonry
35
+ 7.87.2 also counted a visitor's later pages, assets and API calls that carried
36
+ the landing page's utm, about one per minute of the visit, so those hours can
37
+ read several times high and cannot be corrected. Never read a trend across
38
+ that upgrade; for earlier hours quote GA4, or AI visitor journeys where they
39
+ exist.
35
40
 
36
41
  ## Check the instrument before you report a zero
37
42
 
@@ -24,7 +24,12 @@ rarely. Report every step separately; never pool them.
24
24
 
25
25
  Server-side hits are requests and GA4 counts sessions, and each instrument
26
26
  misses some visits the other sees, so the two never match exactly. Compare
27
- their trend, not their totals.
27
+ their trend, not their totals. Server-side arrivals stored before Canonry
28
+ 7.87.2 also counted a visitor's later pages, assets and API calls that carried
29
+ the landing page's utm, about one per minute of the visit, so those hours can
30
+ read several times high and cannot be corrected. Never read a trend across
31
+ that upgrade; for earlier hours quote GA4, or AI visitor journeys where they
32
+ exist.
28
33
 
29
34
  ## Check the instrument before you report a zero
30
35
 
@@ -1054,7 +1054,8 @@ more than 1,000 messages remain afterwards and names the cause. After
1054
1054
  `deadline` or `batch-cap` the drain hit its limit: if the operator approves a
1055
1055
  manual drain, run a manual sync, and if the backlog recurs, get approval to
1056
1056
  shorten the schedule interval or raise the time limit. After `empty-pulls`
1057
- Cloudflare still counted messages it would not return; later syncs pull them.
1057
+ Cloudflare still counted messages it would not return, even after waiting
1058
+ between pulls; later syncs pull them.
1058
1059
 
1059
1060
  Read the [server-side traffic guide](server-side-traffic.md) for token safety,
1060
1061
  route checks, activation order, smoke tests, rollback, and troubleshooting.
@@ -1103,6 +1104,9 @@ operators, crawled paths, referral products, landing paths, daily history, and
1103
1104
  equal prior-window changes. It does not start a sync or provider work. The
1104
1105
  scope is project-wide for Simple and Advanced portfolios; there is no Property,
1105
1106
  Target, or market attribution. Server sessions and GA sessions remain separate.
1107
+ Referral arrivals stored before Canonry 7.87.2 also counted a visitor's later
1108
+ same-site requests, so a window or prior window that reaches back before that
1109
+ upgrade reads high on that side.
1106
1110
 
1107
1111
  ## Google Analytics 4
1108
1112
 
@@ -33,10 +33,21 @@ Legitimate peaks can qualify and small automated bursts can escape the rule.
33
33
  `--burst-threshold` changes the default 100-hit review trigger; the default has
34
34
  not been calibrated against live traffic distributions.
35
35
 
36
- Server counts use short actor windows within ingestion batches, so they are
37
- not GA sessions or verified people. Normalized paths can combine pages;
38
- multiple sources can overlap. No Property, Target or market attribution is
39
- available. These limits apply equally to Simple and Advanced portfolios.
36
+ Server counts are arrivals, not GA sessions or verified people. A request
37
+ whose referer is outside the site (the AI engine's page, or none) is an
38
+ arrival; requests from one visitor (IP and user agent) to the same landing
39
+ page within a minute count once. A later page, asset or API call whose same-site
40
+ referer still carries the engine's utm belongs to that visitor's arrival from
41
+ the same engine for 30 days, in any sync or push, even one that reaches
42
+ Canonry before the landing does. It counts as the arrival only when the
43
+ visitor had none from that engine in those 30 days: a site whose pages a cache
44
+ serves before the logs see them shows nothing else, so a second click from
45
+ the same engine within 30 days is not counted there. Hours stored before Canonry 7.87.2
46
+ counted every later minute of a visit as another arrival and read high;
47
+ hourly rows keep no visitor, so they cannot be corrected. Normalized paths
48
+ can combine pages; multiple sources can overlap. No Property, Target or
49
+ market attribution is available. These limits apply equally to Simple and
50
+ Advanced portfolios.
40
51
 
41
52
  The observed server/GA quotient, rounded to 2 decimals, uses
42
53
  dimension-deduplicated GA sessions, but complete matching coverage and the GA
@@ -61,7 +72,8 @@ Four tables store the shared output from every adapter:
61
72
  | `ai_user_fetch_likely_fake_hourly` | One row per `(project, source, hour, bot, first trust reason)` — requests that claimed a user-triggered agent but were judged likely fake |
62
73
  | `agent_scanner_clients` | One row per `(project, source, client)` — the latest run of scanner probes from one IP (stored as a keyed hash), kept two days so a burst split across batches is still recognized |
63
74
  | `journey_visitor_aliases` | One row per `(project, alias key)` — a visitor key found to be another visitor seen from a new IP (same AI-tagged page, same browser, within 5 seconds); requests under the alias key are kept under that visitor. Both are keyed hashes, never an IP |
64
- | `ai_referral_events_hourly` | One row per `(project, source, hour, product, source_domain, evidence_type, landing_path, status)` — click-through arrivals rolled up by hour |
75
+ | `ai_referral_events_hourly` | One row per `(project, source, hour, product, source_domain, evidence_type, landing_path, status)` — click-through arrivals rolled up by hour; a visitor's later same-site requests are not arrivals |
76
+ | `ai_referral_visitors` | One row per `(project, source, visitor)`: each visitor's latest AI arrival (the visitor is a keyed hash of IP and user agent, never the address), kept 44 days so a later request of the same visit in a later batch is not counted again |
65
77
  | `raw_event_samples` | Bounded forensic samples for spot checks. Source writes plus a startup/daily global sweep enforce 30-day retention; Cloudflare also uses a per-source, per-hour cap |
66
78
 
67
79
  Each `traffic_sources` row is one server-log integration for a project.
@@ -947,10 +959,13 @@ usable value, receipts keep Cloudflare's 14-day maximum plus the margin.
947
959
  Each Queue sync drains in batches of up to 100 messages for as long as
948
960
  Cloudflare reports a backlog, up to a 4-minute time limit per sync
949
961
  (`CANONRY_CLOUDFLARE_QUEUE_SYNC_DEADLINE_MS`, 30 seconds to 15 minutes) and a
950
- 300-pull safety cap. Cloudflare can return a partial or briefly empty batch
951
- while a backlog waits, so a sync stops only when Cloudflare reports no backlog,
952
- two pulls in a row come back empty, or the limit is reached. If a pull fails
953
- after earlier batches were saved, the run ends `partial` and keeps them.
962
+ 300-pull safety cap. Cloudflare can return a partial or empty batch while a
963
+ backlog waits (on a busy Queue, about 3 pulls in 10 come back empty). While 100
964
+ or more messages wait, the sync waits after each empty pull, 0.5, 1, 2, 4 and
965
+ then 8 seconds, and pulls again. It stops when Cloudflare reports no backlog,
966
+ when every wait came back empty, when fewer than 100 messages wait and two
967
+ pulls in a row came back empty, or at the limit. If a pull fails after earlier
968
+ batches were saved, the run ends `partial` and keeps them.
954
969
 
955
970
  Each sync run records what it did and why it stopped in `syncSummary`: pulls,
956
971
  empty pulls, messages pulled and acknowledged, redelivered (duplicate) events,
@@ -964,8 +979,9 @@ the drain) and warns above that, with the cause taken from the last stop
964
979
  reason. After `deadline` or `batch-cap` the drain hit its limit: shorten the
965
980
  `traffic-sync` interval or raise the time limit, or messages will pass the
966
981
  Queue's retention and be dropped. After `empty-pulls` or `unleased-only`
967
- Cloudflare still counted messages it would not return (leased or not yet
968
- visible); later syncs pull them, and raising the time limit does not help.
982
+ Cloudflare still counted messages it would not return, even after the waits
983
+ (leased or not yet visible); later syncs pull them, and raising the time limit
984
+ does not help.
969
985
 
970
986
  ## Syncing data
971
987
 
@@ -10,8 +10,8 @@ import {
10
10
  backfillSnapshotAttributionCommand,
11
11
  backfillTrafficClassificationCommand,
12
12
  replayQueryAuditLog
13
- } from "./chunk-D5V6YQXA.js";
14
- import "./chunk-L5NMS7AU.js";
13
+ } from "./chunk-IE4D47JE.js";
14
+ import "./chunk-BVJA3TV2.js";
15
15
  import "./chunk-2FJB3CSS.js";
16
16
  import "./chunk-HGMYEDAQ.js";
17
17
  import "./chunk-JAYUWQAV.js";
@@ -19,10 +19,10 @@ import "./chunk-IBGZ6D6R.js";
19
19
  import {
20
20
  backfillProjectAnswerMentions,
21
21
  backfillProjectAnswerMentionsInChunks
22
- } from "./chunk-EQGCGZZY.js";
23
- import "./chunk-VDYXB6SV.js";
22
+ } from "./chunk-AI75KS7G.js";
23
+ import "./chunk-POMLL2OZ.js";
24
24
  import "./chunk-GBWCEOZR.js";
25
- import "./chunk-O26FQ7RI.js";
25
+ import "./chunk-AYYZ4HKJ.js";
26
26
  import "./chunk-F643WELJ.js";
27
27
  import "./chunk-MLKGABMK.js";
28
28
  export {
@@ -44,7 +44,7 @@ import {
44
44
  createClient,
45
45
  dashboardSessions,
46
46
  migrate
47
- } from "./chunk-O26FQ7RI.js";
47
+ } from "./chunk-AYYZ4HKJ.js";
48
48
  import {
49
49
  ProviderNames,
50
50
  ProviderReloadErrorReasons
@@ -28,7 +28,7 @@ async function buildSetupState() {
28
28
  }
29
29
  if (dbPath && fs.existsSync(dbPath)) {
30
30
  try {
31
- const { createClient, projects, queries: queriesTable } = await import("./src-SJYGA7NH.js");
31
+ const { createClient, projects, queries: queriesTable } = await import("./src-JQYZ2TP6.js");
32
32
  const db = createClient(dbPath);
33
33
  project_count = db.select({ id: projects.id }).from(projects).all().length;
34
34
  const firstQuery = db.select({ id: queriesTable.id }).from(queriesTable).limit(1).all();
@@ -47,7 +47,7 @@ function queueServeHandoff() {
47
47
  async function runPendingServeHandoff(format) {
48
48
  if (!pendingServeHandoff) return;
49
49
  pendingServeHandoff = false;
50
- const { serveCommand } = await import("./serve-WF5ZXWW6.js");
50
+ const { serveCommand } = await import("./serve-LLIUILD2.js");
51
51
  await serveCommand(format);
52
52
  }
53
53