@agentsean/google 1.0.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 (112) hide show
  1. package/LICENSE +661 -0
  2. package/dist/audit-extras.d.ts +21 -0
  3. package/dist/audit-extras.d.ts.map +1 -0
  4. package/dist/audit-extras.js +62 -0
  5. package/dist/audit-extras.js.map +1 -0
  6. package/dist/broker.d.ts +47 -0
  7. package/dist/broker.d.ts.map +1 -0
  8. package/dist/broker.js +146 -0
  9. package/dist/broker.js.map +1 -0
  10. package/dist/causes.d.ts +157 -0
  11. package/dist/causes.d.ts.map +1 -0
  12. package/dist/causes.js +175 -0
  13. package/dist/causes.js.map +1 -0
  14. package/dist/connect-flow.d.ts +63 -0
  15. package/dist/connect-flow.d.ts.map +1 -0
  16. package/dist/connect-flow.js +150 -0
  17. package/dist/connect-flow.js.map +1 -0
  18. package/dist/crux.d.ts +37 -0
  19. package/dist/crux.d.ts.map +1 -0
  20. package/dist/crux.js +112 -0
  21. package/dist/crux.js.map +1 -0
  22. package/dist/data/changepoints.json +174 -0
  23. package/dist/data/quotas.json +17 -0
  24. package/dist/errors.d.ts +46 -0
  25. package/dist/errors.d.ts.map +1 -0
  26. package/dist/errors.js +110 -0
  27. package/dist/errors.js.map +1 -0
  28. package/dist/ga4.d.ts +46 -0
  29. package/dist/ga4.d.ts.map +1 -0
  30. package/dist/ga4.js +126 -0
  31. package/dist/ga4.js.map +1 -0
  32. package/dist/gsc.d.ts +98 -0
  33. package/dist/gsc.d.ts.map +1 -0
  34. package/dist/gsc.js +141 -0
  35. package/dist/gsc.js.map +1 -0
  36. package/dist/http.d.ts +14 -0
  37. package/dist/http.d.ts.map +1 -0
  38. package/dist/http.js +47 -0
  39. package/dist/http.js.map +1 -0
  40. package/dist/incidents.d.ts +51 -0
  41. package/dist/incidents.d.ts.map +1 -0
  42. package/dist/incidents.js +221 -0
  43. package/dist/incidents.js.map +1 -0
  44. package/dist/index.d.ts +27 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +27 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/integrity.d.ts +32 -0
  49. package/dist/integrity.d.ts.map +1 -0
  50. package/dist/integrity.js +52 -0
  51. package/dist/integrity.js.map +1 -0
  52. package/dist/oauth-broker.d.ts +38 -0
  53. package/dist/oauth-broker.d.ts.map +1 -0
  54. package/dist/oauth-broker.js +81 -0
  55. package/dist/oauth-broker.js.map +1 -0
  56. package/dist/oauth-config.d.ts +16 -0
  57. package/dist/oauth-config.d.ts.map +1 -0
  58. package/dist/oauth-config.js +24 -0
  59. package/dist/oauth-config.js.map +1 -0
  60. package/dist/oauth-desktop.d.ts +29 -0
  61. package/dist/oauth-desktop.d.ts.map +1 -0
  62. package/dist/oauth-desktop.js +76 -0
  63. package/dist/oauth-desktop.js.map +1 -0
  64. package/dist/pending.d.ts +18 -0
  65. package/dist/pending.d.ts.map +1 -0
  66. package/dist/pending.js +29 -0
  67. package/dist/pending.js.map +1 -0
  68. package/dist/persist.d.ts +48 -0
  69. package/dist/persist.d.ts.map +1 -0
  70. package/dist/persist.js +298 -0
  71. package/dist/persist.js.map +1 -0
  72. package/dist/pkce.d.ts +9 -0
  73. package/dist/pkce.d.ts.map +1 -0
  74. package/dist/pkce.js +13 -0
  75. package/dist/pkce.js.map +1 -0
  76. package/dist/psi.d.ts +19 -0
  77. package/dist/psi.d.ts.map +1 -0
  78. package/dist/psi.js +47 -0
  79. package/dist/psi.js.map +1 -0
  80. package/dist/quota.d.ts +22 -0
  81. package/dist/quota.d.ts.map +1 -0
  82. package/dist/quota.js +136 -0
  83. package/dist/quota.js.map +1 -0
  84. package/dist/reconcile.d.ts +19 -0
  85. package/dist/reconcile.d.ts.map +1 -0
  86. package/dist/reconcile.js +89 -0
  87. package/dist/reconcile.js.map +1 -0
  88. package/dist/scopes.d.ts +25 -0
  89. package/dist/scopes.d.ts.map +1 -0
  90. package/dist/scopes.js +49 -0
  91. package/dist/scopes.js.map +1 -0
  92. package/dist/seal.d.ts +4 -0
  93. package/dist/seal.d.ts.map +1 -0
  94. package/dist/seal.js +27 -0
  95. package/dist/seal.js.map +1 -0
  96. package/dist/sync.d.ts +29 -0
  97. package/dist/sync.d.ts.map +1 -0
  98. package/dist/sync.js +266 -0
  99. package/dist/sync.js.map +1 -0
  100. package/dist/tokens.d.ts +57 -0
  101. package/dist/tokens.d.ts.map +1 -0
  102. package/dist/tokens.js +122 -0
  103. package/dist/tokens.js.map +1 -0
  104. package/dist/verification.d.ts +17 -0
  105. package/dist/verification.d.ts.map +1 -0
  106. package/dist/verification.js +51 -0
  107. package/dist/verification.js.map +1 -0
  108. package/dist/waterfall.d.ts +39 -0
  109. package/dist/waterfall.d.ts.map +1 -0
  110. package/dist/waterfall.js +167 -0
  111. package/dist/waterfall.js.map +1 -0
  112. package/package.json +52 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"psi.js","sourceRoot":"","sources":["../src/psi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAmB,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,GAAG,GAAG,4DAA4D,CAAC;AAczE,SAAS,OAAO,CAAC,MAAe,EAAE,EAAU;IAC1C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,CAAC,GAAI,MAAoE,CAAC,EAAE,CAAC,CAAC;IACpF,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,IAAI,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC,YAAY,CAAC;IAC9D,OAAO,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAK5B;IACC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,QAAQ;QACR,QAAQ,EAAE,aAAa;KACxB,CAAC,CAAC;IACH,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACjC,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,MAAM,WAAW,CAC3B,IAAI,CAAC,IAAI,EACT,KAAK,EACL,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAC1B,GAAG,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,EAC7B,EAAE,CACH,CAAC;IACF,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,kBAAkB,CAAC,KAAK,EAAE,wBAAwB,EAAE,MAAM,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAS7B,CAAC;IACF,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC;IACjC,MAAM,MAAM,GAAG,EAAE,EAAE,MAAM,CAAC;IAC1B,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,QAAQ;QACR,gBAAgB,EAAE,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,IAAI,IAAI;QAC5D,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,IAAI,IAAI;QAC5C,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,0BAA0B,CAAC;QAClD,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,2BAA2B,CAAC;QACnD,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,yBAAyB,CAAC;QAC/C,iBAAiB,EAAE,EAAE,EAAE,iBAAiB,IAAI,IAAI;QAChD,GAAG,EAAE,IAAI;KACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { SqliteDatabase } from "@agentsean/db";
2
+ export declare const LIMITS: {
3
+ readonly gscSearchAnalyticsQpm: 1200;
4
+ readonly gscUrlInspectionQpd: 2000;
5
+ readonly gscUrlInspectionQpm: 600;
6
+ readonly gscOtherQpm: 200;
7
+ readonly ga4TokensPerHour: 14000;
8
+ readonly psiQpd: 25000;
9
+ readonly psiQpm: 240;
10
+ readonly cruxQpm: 150;
11
+ };
12
+ export type QuotaApi = "gsc.searchAnalytics" | "gsc.urlInspection" | "gsc.other" | "ga4.data" | "psi" | "crux";
13
+ type WindowKind = "minute" | "hour" | "day";
14
+ export type QuotaManager = {
15
+ acquire: (api: QuotaApi, scopeKey: string, cost?: number) => Promise<void>;
16
+ record: (api: QuotaApi, scopeKey: string, cost?: number) => void;
17
+ used: (api: QuotaApi, scopeKey: string, kind: WindowKind) => number;
18
+ remainingInspectionToday: (siteUrl: string) => number;
19
+ };
20
+ export declare function createQuotaManager(db: SqliteDatabase | null, nowFn?: () => Date): QuotaManager;
21
+ export {};
22
+ //# sourceMappingURL=quota.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota.d.ts","sourceRoot":"","sources":["../src/quota.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,MAAM;;;;;;;;;CAST,CAAC;AAEX,MAAM,MAAM,QAAQ,GAChB,qBAAqB,GACrB,mBAAmB,GACnB,WAAW,GACX,UAAU,GACV,KAAK,GACL,MAAM,CAAC;AAEX,KAAK,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AAkB5C,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,MAAM,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,IAAI,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,MAAM,CAAC;IACpE,wBAAwB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CACvD,CAAC;AA6BF,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,cAAc,GAAG,IAAI,EACzB,KAAK,GAAE,MAAM,IAAuB,GACnC,YAAY,CAoHd"}
package/dist/quota.js ADDED
@@ -0,0 +1,136 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { eq, and } from "drizzle-orm";
3
+ import { quotaUsage } from "@agentsean/db";
4
+ import { QuotaExceededError } from "./errors.js";
5
+ export const LIMITS = {
6
+ gscSearchAnalyticsQpm: 1200,
7
+ gscUrlInspectionQpd: 2000,
8
+ gscUrlInspectionQpm: 600,
9
+ gscOtherQpm: 200,
10
+ ga4TokensPerHour: 14000,
11
+ psiQpd: 25000,
12
+ psiQpm: 240,
13
+ cruxQpm: 150,
14
+ };
15
+ function utcMinute(d) {
16
+ return d.toISOString().slice(0, 16) + ":00.000Z";
17
+ }
18
+ function utcHour(d) {
19
+ return d.toISOString().slice(0, 13) + ":00:00.000Z";
20
+ }
21
+ function utcDay(d) {
22
+ return d.toISOString().slice(0, 10) + "T00:00:00.000Z";
23
+ }
24
+ function windowStart(kind, now) {
25
+ if (kind === "minute")
26
+ return utcMinute(now);
27
+ if (kind === "hour")
28
+ return utcHour(now);
29
+ return utcDay(now);
30
+ }
31
+ function keyOf(api, scope, kind, start) {
32
+ return `${api}|${scope}|${kind}|${start}`;
33
+ }
34
+ function limitsFor(api) {
35
+ switch (api) {
36
+ case "gsc.searchAnalytics":
37
+ return [{ kind: "minute", limit: LIMITS.gscSearchAnalyticsQpm }];
38
+ case "gsc.urlInspection":
39
+ return [
40
+ { kind: "day", limit: LIMITS.gscUrlInspectionQpd },
41
+ { kind: "minute", limit: LIMITS.gscUrlInspectionQpm },
42
+ ];
43
+ case "gsc.other":
44
+ return [{ kind: "minute", limit: LIMITS.gscOtherQpm }];
45
+ case "ga4.data":
46
+ return [{ kind: "hour", limit: LIMITS.ga4TokensPerHour }];
47
+ case "psi":
48
+ return [
49
+ { kind: "day", limit: LIMITS.psiQpd },
50
+ { kind: "minute", limit: LIMITS.psiQpm },
51
+ ];
52
+ case "crux":
53
+ return [{ kind: "minute", limit: LIMITS.cruxQpm }];
54
+ }
55
+ }
56
+ export function createQuotaManager(db, nowFn = () => new Date()) {
57
+ const mem = new Map();
58
+ const read = (api, scope, kind, start) => {
59
+ const k = keyOf(api, scope, kind, start);
60
+ const hit = mem.get(k);
61
+ if (hit !== undefined)
62
+ return hit;
63
+ if (!db)
64
+ return 0;
65
+ const row = db
66
+ .select()
67
+ .from(quotaUsage)
68
+ .where(and(eq(quotaUsage.api, api), eq(quotaUsage.scopeKey, scope), eq(quotaUsage.windowKind, kind), eq(quotaUsage.windowStart, start)))
69
+ .get();
70
+ const n = row?.count ?? 0;
71
+ mem.set(k, n);
72
+ return n;
73
+ };
74
+ const write = (api, scope, kind, start, count, limit) => {
75
+ const k = keyOf(api, scope, kind, start);
76
+ mem.set(k, count);
77
+ if (!db)
78
+ return;
79
+ const now = nowFn().toISOString();
80
+ const existing = db
81
+ .select()
82
+ .from(quotaUsage)
83
+ .where(and(eq(quotaUsage.api, api), eq(quotaUsage.scopeKey, scope), eq(quotaUsage.windowKind, kind), eq(quotaUsage.windowStart, start)))
84
+ .get();
85
+ if (existing) {
86
+ db.update(quotaUsage)
87
+ .set({ count, updatedAt: now })
88
+ .where(eq(quotaUsage.id, existing.id))
89
+ .run();
90
+ return;
91
+ }
92
+ db.insert(quotaUsage)
93
+ .values({
94
+ id: randomUUID(),
95
+ api,
96
+ scopeKey: scope,
97
+ windowKind: kind,
98
+ windowStart: start,
99
+ count,
100
+ limitCount: limit,
101
+ updatedAt: now,
102
+ })
103
+ .run();
104
+ };
105
+ const record = (api, scopeKey, cost = 1) => {
106
+ const now = nowFn();
107
+ for (const { kind, limit } of limitsFor(api)) {
108
+ const start = windowStart(kind, now);
109
+ const next = read(api, scopeKey, kind, start) + cost;
110
+ write(api, scopeKey, kind, start, next, limit);
111
+ }
112
+ };
113
+ return {
114
+ acquire: async (api, scopeKey, cost = 1) => {
115
+ const now = nowFn();
116
+ for (const { kind, limit } of limitsFor(api)) {
117
+ const start = windowStart(kind, now);
118
+ const used = read(api, scopeKey, kind, start);
119
+ if (used + cost > limit) {
120
+ const retry = kind === "minute" ? 60_000 : kind === "hour" ? 15 * 60_000 : 60 * 60_000;
121
+ throw new QuotaExceededError(api, `${api} quota exceeded for ${scopeKey} (${used}/${limit} per ${kind})`, retry);
122
+ }
123
+ }
124
+ },
125
+ record,
126
+ used: (api, scopeKey, kind) => {
127
+ const start = windowStart(kind, nowFn());
128
+ return read(api, scopeKey, kind, start);
129
+ },
130
+ remainingInspectionToday: (siteUrl) => {
131
+ const used = read("gsc.urlInspection", siteUrl, "day", windowStart("day", nowFn()));
132
+ return Math.max(0, LIMITS.gscUrlInspectionQpd - used);
133
+ },
134
+ };
135
+ }
136
+ //# sourceMappingURL=quota.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota.js","sourceRoot":"","sources":["../src/quota.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { SqliteDatabase } from "@agentsean/db";
2
+ export type ResidualRow = {
3
+ date: string;
4
+ gscClicks: number;
5
+ ga4OrganicSessions: number;
6
+ residual: number;
7
+ residualPct: number | null;
8
+ overlappingIncidentIds: string[];
9
+ notes: string;
10
+ };
11
+ /**
12
+ * GSC clicks vs GA4 Google-organic sessions. They will not match:
13
+ * sessions can contain multiple landing-page clicks, attribution differs,
14
+ * consent mode drops GA4, GSC de-bots server-side. The residual is the
15
+ * explicit gap, not a bug. Annotate dates that overlap Google updates.
16
+ */
17
+ export declare function computeResidual(gscClicks: number, ga4OrganicSessions: number): ResidualRow;
18
+ export declare function reconcileSite(db: SqliteDatabase, siteId: string): ResidualRow[];
19
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,MAAM,GACzB,WAAW,CAYb;AAUD,wBAAgB,aAAa,CAAC,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CA8B/E"}
@@ -0,0 +1,89 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { and, eq } from "drizzle-orm";
3
+ import { ga4Daily, gscDaily, gscGa4Reconciliation } from "@agentsean/db";
4
+ import { changepointsOverlapping } from "./incidents.js";
5
+ /**
6
+ * GSC clicks vs GA4 Google-organic sessions. They will not match:
7
+ * sessions can contain multiple landing-page clicks, attribution differs,
8
+ * consent mode drops GA4, GSC de-bots server-side. The residual is the
9
+ * explicit gap, not a bug. Annotate dates that overlap Google updates.
10
+ */
11
+ export function computeResidual(gscClicks, ga4OrganicSessions) {
12
+ const residual = ga4OrganicSessions - gscClicks;
13
+ const denom = Math.max(gscClicks, ga4OrganicSessions, 1);
14
+ return {
15
+ date: "",
16
+ gscClicks,
17
+ ga4OrganicSessions,
18
+ residual,
19
+ residualPct: Math.round((residual / denom) * 10000) / 10000,
20
+ overlappingIncidentIds: [],
21
+ notes: residualNote(gscClicks, ga4OrganicSessions),
22
+ };
23
+ }
24
+ function residualNote(gsc, ga4) {
25
+ if (gsc === 0 && ga4 === 0)
26
+ return "both series empty";
27
+ if (ga4 === 0)
28
+ return "GA4 organic sessions are zero — check tracking / consent mode";
29
+ if (gsc === 0)
30
+ return "GSC clicks are zero — property may be unverified or still lagging";
31
+ return "residual = GA4 Google-organic sessions − GSC clicks (expected; not a data bug)";
32
+ }
33
+ export function reconcileSite(db, siteId) {
34
+ const gsc = db.select().from(gscDaily).where(eq(gscDaily.siteId, siteId)).all();
35
+ const ga4 = db.select().from(ga4Daily).where(eq(ga4Daily.siteId, siteId)).all();
36
+ const gscByDate = new Map();
37
+ for (const row of gsc) {
38
+ if (row.searchType !== "web")
39
+ continue;
40
+ gscByDate.set(row.date, (gscByDate.get(row.date) ?? 0) + row.clicks);
41
+ }
42
+ const ga4ByDate = new Map();
43
+ for (const row of ga4) {
44
+ ga4ByDate.set(row.date, row.organicSessions);
45
+ }
46
+ const dates = [...new Set([...gscByDate.keys(), ...ga4ByDate.keys()])].toSorted();
47
+ const out = [];
48
+ for (const date of dates) {
49
+ const base = computeResidual(gscByDate.get(date) ?? 0, ga4ByDate.get(date) ?? 0);
50
+ const overlapping = changepointsOverlapping(db, date, date);
51
+ const row = {
52
+ ...base,
53
+ date,
54
+ overlappingIncidentIds: overlapping.map((c) => c.id),
55
+ notes: overlapping.length > 0
56
+ ? `${base.notes}; Google updates: ${overlapping.map((c) => c.title).join("; ")}`
57
+ : base.notes,
58
+ };
59
+ out.push(row);
60
+ persistResidual(db, siteId, row);
61
+ }
62
+ return out;
63
+ }
64
+ function persistResidual(db, siteId, row) {
65
+ const existing = db
66
+ .select()
67
+ .from(gscGa4Reconciliation)
68
+ .where(and(eq(gscGa4Reconciliation.siteId, siteId), eq(gscGa4Reconciliation.date, row.date)))
69
+ .get();
70
+ const values = {
71
+ gscClicks: row.gscClicks,
72
+ ga4OrganicSessions: row.ga4OrganicSessions,
73
+ residual: row.residual,
74
+ residualPct: row.residualPct,
75
+ overlappingIncidentIds: JSON.stringify(row.overlappingIncidentIds),
76
+ notes: row.notes,
77
+ };
78
+ if (existing) {
79
+ db.update(gscGa4Reconciliation)
80
+ .set(values)
81
+ .where(eq(gscGa4Reconciliation.id, existing.id))
82
+ .run();
83
+ return;
84
+ }
85
+ db.insert(gscGa4Reconciliation)
86
+ .values({ id: randomUUID(), siteId, date: row.date, ...values })
87
+ .run();
88
+ }
89
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /** Scopes declared on the verification submission (docs/oauth-verification.md).
2
+ * Requested incrementally at runtime. business.manage waits for Phase 9. */
3
+ export declare const GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
4
+ export declare const GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
5
+ export declare const GOOGLE_USERINFO_URL = "https://openidconnect.googleapis.com/v1/userinfo";
6
+ export declare const SCOPE: {
7
+ readonly openid: "openid";
8
+ readonly email: "https://www.googleapis.com/auth/userinfo.email";
9
+ readonly profile: "https://www.googleapis.com/auth/userinfo.profile";
10
+ readonly webmastersReadonly: "https://www.googleapis.com/auth/webmasters.readonly";
11
+ readonly webmasters: "https://www.googleapis.com/auth/webmasters";
12
+ readonly analyticsReadonly: "https://www.googleapis.com/auth/analytics.readonly";
13
+ readonly siteVerification: "https://www.googleapis.com/auth/siteverification";
14
+ readonly businessManage: "https://www.googleapis.com/auth/business.manage";
15
+ };
16
+ /** First-connect set: GSC read+write (property add + sitemap submit), GA4, Site Verification. */
17
+ export declare const CONNECT_SCOPES: readonly string[];
18
+ export declare const DEFAULT_BROKER_URL = "https://oauth.agentsean.com";
19
+ export declare const GOOGLE_OAUTH_ACCOUNT = "google-oauth";
20
+ export declare const GOOGLE_API_KEY_ACCOUNT = "google-api-key";
21
+ export declare const GOOGLE_BYO_CLIENT_ACCOUNT = "google-byo-client";
22
+ export declare function encodeSiteUrl(siteUrl: string): string;
23
+ /** URL-prefix properties must keep the trailing slash. Domain properties are sc-domain:. */
24
+ export declare function normalizeGscSiteUrl(input: string): string;
25
+ //# sourceMappingURL=scopes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../src/scopes.ts"],"names":[],"mappings":"AAAA;6EAC6E;AAE7E,eAAO,MAAM,eAAe,iDAAiD,CAAC;AAC9E,eAAO,MAAM,gBAAgB,wCAAwC,CAAC;AACtE,eAAO,MAAM,mBAAmB,qDAAqD,CAAC;AAEtF,eAAO,MAAM,KAAK;;;;;;;;;CASR,CAAC;AAEX,iGAAiG;AACjG,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAO3C,CAAC;AAEF,eAAO,MAAM,kBAAkB,gCAAgC,CAAC;AAEhE,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AACnD,eAAO,MAAM,sBAAsB,mBAAmB,CAAC;AACvD,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,4FAA4F;AAC5F,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWzD"}
package/dist/scopes.js ADDED
@@ -0,0 +1,49 @@
1
+ /** Scopes declared on the verification submission (docs/oauth-verification.md).
2
+ * Requested incrementally at runtime. business.manage waits for Phase 9. */
3
+ export const GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
4
+ export const GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
5
+ export const GOOGLE_USERINFO_URL = "https://openidconnect.googleapis.com/v1/userinfo";
6
+ export const SCOPE = {
7
+ openid: "openid",
8
+ email: "https://www.googleapis.com/auth/userinfo.email",
9
+ profile: "https://www.googleapis.com/auth/userinfo.profile",
10
+ webmastersReadonly: "https://www.googleapis.com/auth/webmasters.readonly",
11
+ webmasters: "https://www.googleapis.com/auth/webmasters",
12
+ analyticsReadonly: "https://www.googleapis.com/auth/analytics.readonly",
13
+ siteVerification: "https://www.googleapis.com/auth/siteverification",
14
+ businessManage: "https://www.googleapis.com/auth/business.manage",
15
+ };
16
+ /** First-connect set: GSC read+write (property add + sitemap submit), GA4, Site Verification. */
17
+ export const CONNECT_SCOPES = [
18
+ SCOPE.openid,
19
+ SCOPE.email,
20
+ SCOPE.profile,
21
+ SCOPE.webmasters,
22
+ SCOPE.analyticsReadonly,
23
+ SCOPE.siteVerification,
24
+ ];
25
+ export const DEFAULT_BROKER_URL = "https://oauth.agentsean.com";
26
+ export const GOOGLE_OAUTH_ACCOUNT = "google-oauth";
27
+ export const GOOGLE_API_KEY_ACCOUNT = "google-api-key";
28
+ export const GOOGLE_BYO_CLIENT_ACCOUNT = "google-byo-client";
29
+ export function encodeSiteUrl(siteUrl) {
30
+ return encodeURIComponent(siteUrl);
31
+ }
32
+ /** URL-prefix properties must keep the trailing slash. Domain properties are sc-domain:. */
33
+ export function normalizeGscSiteUrl(input) {
34
+ const trimmed = input.trim();
35
+ if (trimmed.startsWith("sc-domain:"))
36
+ return trimmed;
37
+ try {
38
+ const u = new URL(trimmed);
39
+ if (!u.pathname || u.pathname === "")
40
+ u.pathname = "/";
41
+ if (!u.pathname.endsWith("/"))
42
+ u.pathname += "/";
43
+ return u.origin + u.pathname;
44
+ }
45
+ catch {
46
+ return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
47
+ }
48
+ }
49
+ //# sourceMappingURL=scopes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopes.js","sourceRoot":"","sources":["../src/scopes.ts"],"names":[],"mappings":"AAAA;6EAC6E;AAE7E,MAAM,CAAC,MAAM,eAAe,GAAG,8CAA8C,CAAC;AAC9E,MAAM,CAAC,MAAM,gBAAgB,GAAG,qCAAqC,CAAC;AACtE,MAAM,CAAC,MAAM,mBAAmB,GAAG,kDAAkD,CAAC;AAEtF,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,gDAAgD;IACvD,OAAO,EAAE,kDAAkD;IAC3D,kBAAkB,EAAE,qDAAqD;IACzE,UAAU,EAAE,4CAA4C;IACxD,iBAAiB,EAAE,oDAAoD;IACvE,gBAAgB,EAAE,kDAAkD;IACpE,cAAc,EAAE,iDAAiD;CACzD,CAAC;AAEX,iGAAiG;AACjG,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,KAAK,CAAC,MAAM;IACZ,KAAK,CAAC,KAAK;IACX,KAAK,CAAC,OAAO;IACb,KAAK,CAAC,UAAU;IAChB,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,gBAAgB;CACvB,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,6BAA6B,CAAC;AAEhE,MAAM,CAAC,MAAM,oBAAoB,GAAG,cAAc,CAAC;AACnD,MAAM,CAAC,MAAM,sBAAsB,GAAG,gBAAgB,CAAC;AACvD,MAAM,CAAC,MAAM,yBAAyB,GAAG,mBAAmB,CAAC;AAE7D,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,OAAO,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,EAAE;YAAE,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC;QACvD,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,CAAC,CAAC,QAAQ,IAAI,GAAG,CAAC;QACjD,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC;IACzD,CAAC;AACH,CAAC"}
package/dist/seal.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ /** AES-256-GCM sealed handoff. Ciphertext is iv || tag || body, base64url. */
2
+ export declare function seal(key: Buffer, plaintext: string): string;
3
+ export declare function unseal(key: Buffer, payload: string): string;
4
+ //# sourceMappingURL=seal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seal.d.ts","sourceRoot":"","sources":["../src/seal.ts"],"names":[],"mappings":"AAKA,8EAA8E;AAC9E,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAO3D;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAU3D"}
package/dist/seal.js ADDED
@@ -0,0 +1,27 @@
1
+ import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
2
+ const IV_LEN = 12;
3
+ const TAG_LEN = 16;
4
+ /** AES-256-GCM sealed handoff. Ciphertext is iv || tag || body, base64url. */
5
+ export function seal(key, plaintext) {
6
+ if (key.length !== 32)
7
+ throw new Error("wrap key must be 32 bytes");
8
+ const iv = randomBytes(IV_LEN);
9
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
10
+ const enc = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
11
+ const tag = cipher.getAuthTag();
12
+ return Buffer.concat([iv, tag, enc]).toString("base64url");
13
+ }
14
+ export function unseal(key, payload) {
15
+ if (key.length !== 32)
16
+ throw new Error("wrap key must be 32 bytes");
17
+ const buf = Buffer.from(payload, "base64url");
18
+ if (buf.length < IV_LEN + TAG_LEN + 1)
19
+ throw new Error("handoff payload too short");
20
+ const iv = buf.subarray(0, IV_LEN);
21
+ const tag = buf.subarray(IV_LEN, IV_LEN + TAG_LEN);
22
+ const body = buf.subarray(IV_LEN + TAG_LEN);
23
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
24
+ decipher.setAuthTag(tag);
25
+ return Buffer.concat([decipher.update(body), decipher.final()]).toString("utf8");
26
+ }
27
+ //# sourceMappingURL=seal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seal.js","sourceRoot":"","sources":["../src/seal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE5E,MAAM,MAAM,GAAG,EAAE,CAAC;AAClB,MAAM,OAAO,GAAG,EAAE,CAAC;AAEnB,8EAA8E;AAC9E,MAAM,UAAU,IAAI,CAAC,GAAW,EAAE,SAAiB;IACjD,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACpE,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAChC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAW,EAAE,OAAe;IACjD,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC9C,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACpF,MAAM,EAAE,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAC1D,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACzB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACnF,CAAC"}
package/dist/sync.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import type { SqliteDatabase } from "@agentsean/db";
2
+ import type { CredentialStore } from "@agentsean/credentials";
3
+ import { type FetchFn } from "./http.js";
4
+ import { type ResidualRow } from "./reconcile.js";
5
+ export type SyncResult = {
6
+ gscDays: number;
7
+ gscPages: number;
8
+ gscQueries: number;
9
+ ga4Days: number;
10
+ crux: boolean;
11
+ psi: boolean;
12
+ incidents: number;
13
+ residualRows: ResidualRow[];
14
+ inspectionRemaining: number;
15
+ testingModeSuspected: boolean;
16
+ errors: string[];
17
+ };
18
+ export type SyncDeps = {
19
+ db: SqliteDatabase;
20
+ store: CredentialStore;
21
+ fetch?: FetchFn | undefined;
22
+ siteId: string;
23
+ inspectUrls?: string[] | undefined;
24
+ runPsiAudit?: boolean | undefined;
25
+ sleep?: ((ms: number) => Promise<void>) | undefined;
26
+ maxBackoffMs?: number | undefined;
27
+ };
28
+ export declare function syncGoogle(deps: SyncDeps): Promise<SyncResult>;
29
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAgB,KAAK,OAAO,EAAmB,MAAM,WAAW,CAAC;AAexE,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAgBjE,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,cAAc,CAAC;IACnB,KAAK,EAAE,eAAe,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACpD,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC,CAAC;AAgCF,wBAAsB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAkHpE"}