stitchkit 0.80.1 → 0.81.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 (177) hide show
  1. package/dist/agent-runtime/provider-failure.d.ts.map +1 -1
  2. package/dist/agent-runtime-coding-tools.js +1 -1
  3. package/dist/agent-runtime-harness.js +7 -5
  4. package/dist/agent-runtime.js +15 -19
  5. package/dist/application/notification-outbox.d.ts +80 -0
  6. package/dist/application/notification-outbox.d.ts.map +1 -0
  7. package/dist/application/process-lifecycle.d.ts +166 -0
  8. package/dist/application/process-lifecycle.d.ts.map +1 -0
  9. package/dist/application/state-store.d.ts +18 -0
  10. package/dist/application/state-store.d.ts.map +1 -0
  11. package/dist/application.d.ts +3 -0
  12. package/dist/application.d.ts.map +1 -1
  13. package/dist/application.js +568 -11
  14. package/dist/browser/http.d.ts +14 -0
  15. package/dist/browser/http.d.ts.map +1 -1
  16. package/dist/browser/resumable.d.ts +6 -0
  17. package/dist/browser/resumable.d.ts.map +1 -1
  18. package/dist/cli.js +9 -7
  19. package/dist/contract/define.d.ts +27 -4
  20. package/dist/contract/define.d.ts.map +1 -1
  21. package/dist/contract/errors-factory.d.ts +22 -3
  22. package/dist/contract/errors-factory.d.ts.map +1 -1
  23. package/dist/contract/index.d.ts +2 -2
  24. package/dist/contract/index.d.ts.map +1 -1
  25. package/dist/contract/index.js +1 -1
  26. package/dist/geo/index.d.ts +4 -0
  27. package/dist/geo/index.d.ts.map +1 -0
  28. package/dist/geo/maxmind.d.ts +4 -0
  29. package/dist/geo/maxmind.d.ts.map +1 -0
  30. package/dist/geo/resolver.d.ts +9 -0
  31. package/dist/geo/resolver.d.ts.map +1 -0
  32. package/dist/geo/types.d.ts +59 -0
  33. package/dist/geo/types.d.ts.map +1 -0
  34. package/dist/geo.d.ts +3 -0
  35. package/dist/geo.d.ts.map +1 -0
  36. package/dist/geo.js +245 -0
  37. package/dist/{index-9s6z8vgf.js → index-1dd82z59.js} +1 -1
  38. package/dist/{index-vwp69871.js → index-27487ay5.js} +4 -4
  39. package/dist/{index-7ag81v2f.js → index-27gm3d6g.js} +10 -321
  40. package/dist/{index-y01f4223.js → index-2bxcmqkb.js} +127 -43
  41. package/dist/{index-dxesg10d.js → index-3ds42w1w.js} +3 -3
  42. package/dist/index-3xwxfj4z.js +334 -0
  43. package/dist/{index-egaabxkz.js → index-5z8tezpx.js} +2 -2
  44. package/dist/{index-fxz0v7vg.js → index-7evdsyez.js} +1 -83
  45. package/dist/{index-xcetq6j3.js → index-90d7h2cr.js} +32 -13
  46. package/dist/{index-t0z5p5w6.js → index-apn8repm.js} +1 -1
  47. package/dist/{index-758zx2ha.js → index-dggwnnjv.js} +2 -2
  48. package/dist/{index-dwf1f2ap.js → index-f9mb610r.js} +1 -62
  49. package/dist/{index-5mtc969c.js → index-fwbkp2jn.js} +1 -1
  50. package/dist/index-p13mwz16.js +16 -0
  51. package/dist/{index-m9kzax52.js → index-p18f59zy.js} +21 -5
  52. package/dist/{index-hb5pf3s4.js → index-qmgs7y68.js} +1 -1
  53. package/dist/{index-2rwwmr7v.js → index-s4ckmrac.js} +1 -1
  54. package/dist/{index-h4pj6fta.js → index-s8cnx02s.js} +8 -5
  55. package/dist/{index-k9ay6v6d.js → index-vchzar7e.js} +74 -23
  56. package/dist/index-vsbzgd7b.js +84 -0
  57. package/dist/{index-dxjjv399.js → index-xbppf54a.js} +95 -15
  58. package/dist/index-y91ry9h2.js +4 -0
  59. package/dist/index-zcgf3gqf.js +83 -0
  60. package/dist/index.js +17 -13
  61. package/dist/internal/error-message.d.ts +3 -0
  62. package/dist/internal/error-message.d.ts.map +1 -0
  63. package/dist/internal/media-type.d.ts +8 -0
  64. package/dist/internal/media-type.d.ts.map +1 -0
  65. package/dist/internal/route-pattern.d.ts +21 -0
  66. package/dist/internal/route-pattern.d.ts.map +1 -1
  67. package/dist/node.js +9 -6
  68. package/dist/observability/audit.d.ts +28 -1
  69. package/dist/observability/audit.d.ts.map +1 -1
  70. package/dist/observability/bounded-logger.d.ts +20 -0
  71. package/dist/observability/bounded-logger.d.ts.map +1 -0
  72. package/dist/observability/context.d.ts +12 -3
  73. package/dist/observability/context.d.ts.map +1 -1
  74. package/dist/observability/index.d.ts +3 -2
  75. package/dist/observability/index.d.ts.map +1 -1
  76. package/dist/observability/index.js +138 -8
  77. package/dist/observability/sanitize.d.ts +17 -0
  78. package/dist/observability/sanitize.d.ts.map +1 -1
  79. package/dist/primitives.js +1 -1
  80. package/dist/react/query-client.d.ts +33 -0
  81. package/dist/react/query-client.d.ts.map +1 -0
  82. package/dist/react.d.ts +1 -0
  83. package/dist/react.d.ts.map +1 -1
  84. package/dist/react.js +83 -1
  85. package/dist/realtime/registry.d.ts +93 -0
  86. package/dist/realtime/registry.d.ts.map +1 -0
  87. package/dist/release/header.d.ts +9 -0
  88. package/dist/release/header.d.ts.map +1 -0
  89. package/dist/release/marker.d.ts +39 -0
  90. package/dist/release/marker.d.ts.map +1 -0
  91. package/dist/release/socket.d.ts +44 -0
  92. package/dist/release/socket.d.ts.map +1 -0
  93. package/dist/release/watcher.d.ts +66 -0
  94. package/dist/release/watcher.d.ts.map +1 -0
  95. package/dist/release.d.ts +15 -0
  96. package/dist/release.d.ts.map +1 -0
  97. package/dist/release.js +196 -0
  98. package/dist/remote.js +12 -7
  99. package/dist/server/context.d.ts +2 -1
  100. package/dist/server/context.d.ts.map +1 -1
  101. package/dist/server/create.d.ts.map +1 -1
  102. package/dist/server/error-hook.d.ts +17 -16
  103. package/dist/server/error-hook.d.ts.map +1 -1
  104. package/dist/server/file-state-store.d.ts +23 -0
  105. package/dist/server/file-state-store.d.ts.map +1 -0
  106. package/dist/server/implement.d.ts.map +1 -1
  107. package/dist/server/index.d.ts +5 -2
  108. package/dist/server/index.d.ts.map +1 -1
  109. package/dist/server/index.js +469 -11
  110. package/dist/server/middleware/cookies.d.ts +33 -1
  111. package/dist/server/middleware/cookies.d.ts.map +1 -1
  112. package/dist/server/middleware/cors.d.ts +16 -1
  113. package/dist/server/middleware/cors.d.ts.map +1 -1
  114. package/dist/server/openapi.d.ts.map +1 -1
  115. package/dist/server/release-signal.d.ts +35 -0
  116. package/dist/server/release-signal.d.ts.map +1 -0
  117. package/dist/server/router.d.ts.map +1 -1
  118. package/dist/server/types.d.ts +26 -2
  119. package/dist/server/types.d.ts.map +1 -1
  120. package/dist/testing/surface-manifest.d.ts.map +1 -1
  121. package/dist/testing.js +7 -4
  122. package/dist/tool-invoker.js +8 -6
  123. package/dist/tools/download-core.d.ts.map +1 -1
  124. package/dist/tools/remote.d.ts.map +1 -1
  125. package/dist/tools/view-file.d.ts.map +1 -1
  126. package/dist/tools.js +20 -16
  127. package/dist/tracking/attribution.d.ts +51 -0
  128. package/dist/tracking/attribution.d.ts.map +1 -0
  129. package/dist/tracking/beacon.d.ts +14 -0
  130. package/dist/tracking/beacon.d.ts.map +1 -0
  131. package/dist/tracking/clicks.d.ts +46 -0
  132. package/dist/tracking/clicks.d.ts.map +1 -0
  133. package/dist/tracking/client.d.ts +121 -0
  134. package/dist/tracking/client.d.ts.map +1 -0
  135. package/dist/tracking/contract.d.ts +46 -0
  136. package/dist/tracking/contract.d.ts.map +1 -0
  137. package/dist/tracking/delivery.d.ts +24 -0
  138. package/dist/tracking/delivery.d.ts.map +1 -0
  139. package/dist/tracking/host.d.ts +43 -0
  140. package/dist/tracking/host.d.ts.map +1 -0
  141. package/dist/tracking/once-per-page.d.ts +17 -0
  142. package/dist/tracking/once-per-page.d.ts.map +1 -0
  143. package/dist/tracking/outbox-storage-indexeddb.d.ts +12 -0
  144. package/dist/tracking/outbox-storage-indexeddb.d.ts.map +1 -0
  145. package/dist/tracking/outbox-storage-memory.d.ts +12 -0
  146. package/dist/tracking/outbox-storage-memory.d.ts.map +1 -0
  147. package/dist/tracking/outbox.d.ts +98 -0
  148. package/dist/tracking/outbox.d.ts.map +1 -0
  149. package/dist/tracking/schemas.d.ts +183 -0
  150. package/dist/tracking/schemas.d.ts.map +1 -0
  151. package/dist/tracking/scroll.d.ts +22 -0
  152. package/dist/tracking/scroll.d.ts.map +1 -0
  153. package/dist/tracking/sequence-reserve.d.ts +34 -0
  154. package/dist/tracking/sequence-reserve.d.ts.map +1 -0
  155. package/dist/tracking/server/active-interval.d.ts +26 -0
  156. package/dist/tracking/server/active-interval.d.ts.map +1 -0
  157. package/dist/tracking/server/bot.d.ts +9 -0
  158. package/dist/tracking/server/bot.d.ts.map +1 -0
  159. package/dist/tracking/server/disposition.d.ts +55 -0
  160. package/dist/tracking/server/disposition.d.ts.map +1 -0
  161. package/dist/tracking/server/hash.d.ts +13 -0
  162. package/dist/tracking/server/hash.d.ts.map +1 -0
  163. package/dist/tracking/server/presence.d.ts +27 -0
  164. package/dist/tracking/server/presence.d.ts.map +1 -0
  165. package/dist/tracking/server/visit-lease.d.ts +92 -0
  166. package/dist/tracking/server/visit-lease.d.ts.map +1 -0
  167. package/dist/tracking/visible-time.d.ts +38 -0
  168. package/dist/tracking/visible-time.d.ts.map +1 -0
  169. package/dist/tracking-server.d.ts +14 -0
  170. package/dist/tracking-server.d.ts.map +1 -0
  171. package/dist/tracking-server.js +173 -0
  172. package/dist/tracking.d.ts +24 -0
  173. package/dist/tracking.d.ts.map +1 -0
  174. package/dist/tracking.js +1090 -0
  175. package/llms-full.txt +938 -29
  176. package/llms.txt +4 -0
  177. package/package.json +25 -4
@@ -0,0 +1,55 @@
1
+ import type { TrackingDisposition } from '../schemas.js';
2
+ /** What the decision needs from a stored visit. */
3
+ export interface KnownVisit {
4
+ id: string;
5
+ browserStreamId: string;
6
+ /** The visit's owner, or `null` for an anonymous visit. */
7
+ ownerId: string | null;
8
+ }
9
+ /** The least an incoming event needs for the decision. */
10
+ export interface DispositionEvent {
11
+ eventId: string;
12
+ visitId: string;
13
+ browserStreamId: string;
14
+ }
15
+ export interface DispositionInput<TEvent extends DispositionEvent> {
16
+ events: readonly TEvent[];
17
+ /** The visits the batch names, as the application read them. */
18
+ visits: readonly KnownVisit[];
19
+ /** `eventId → stored payload hash` for the batch's ids the application already holds. */
20
+ existing: ReadonlyMap<string, string>;
21
+ /** The caller's identity, or `null` for an anonymous caller. */
22
+ actorOwnerId: string | null;
23
+ userAgent?: string | null;
24
+ botPattern?: RegExp;
25
+ }
26
+ export interface DispositionResult<TEvent extends DispositionEvent> {
27
+ /** Events to write, in batch order. */
28
+ accepted: TEvent[];
29
+ /** One per incoming event, in batch order. */
30
+ dispositions: TrackingDisposition[];
31
+ /** Duplicates whose payload differs from the stored one — worth a warning. */
32
+ conflicts: string[];
33
+ /**
34
+ * Anonymous visits the batch names while the caller is identified: the
35
+ * application may adopt them (assign the owner, back-fill the events, record
36
+ * the merge) in the same transaction it writes the batch with.
37
+ */
38
+ adoptable: string[];
39
+ }
40
+ /**
41
+ * Decide every event of a batch without touching storage.
42
+ *
43
+ * - a bot's batch is `excluded-bot` in full, and nothing is written;
44
+ * - an event naming a visit the batch's browser does not own — unknown, a
45
+ * different lineage, or owned by someone else — is `identity-invalid`;
46
+ * - an `eventId` already stored is `duplicate` (a redelivery), and a
47
+ * `conflict` besides if the payload changed;
48
+ * - the rest is `accepted`.
49
+ *
50
+ * An anonymous visit (`ownerId: null`) accepts events from anyone holding the
51
+ * lineage: that is the visit that started before sign-in. When the caller is
52
+ * identified it is also listed as `adoptable`.
53
+ */
54
+ export declare function dispositionTrackingBatch<TEvent extends DispositionEvent>({ events, visits, existing, actorOwnerId, userAgent, botPattern, }: DispositionInput<TEvent>): DispositionResult<TEvent>;
55
+ //# sourceMappingURL=disposition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disposition.d.ts","sourceRoot":"","sources":["../../../src/tracking/server/disposition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAItD,mDAAmD;AACnD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB,CAAC,MAAM,SAAS,gBAAgB;IAC/D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,gEAAgE;IAChE,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IAC9B,yFAAyF;IACzF,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gEAAgE;IAChE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB,CAAC,MAAM,SAAS,gBAAgB;IAChE,uCAAuC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8CAA8C;IAC9C,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC,8EAA8E;IAC9E,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;;;OAIG;IACH,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,SAAS,gBAAgB,EAAE,EACxE,MAAM,EACN,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,UAA2C,GAC5C,EAAE,gBAAgB,CAAC,MAAM,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,CA4CtD"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The payload hash stored beside an accepted event, and compared when the same
3
+ * `eventId` arrives again: an identical hash is a benign redelivery, a
4
+ * different one is a conflict worth a warning.
5
+ *
6
+ * Deliberately `sha256(JSON.stringify(event))` over the **schema-parsed**
7
+ * value, with no key sorting: that is exactly what consuming applications
8
+ * already store, and zod fixes key order when it parses, so the hash is
9
+ * stable. A canonicalised form would mismatch every stored hash for the seven
10
+ * days an outbox can hold an event.
11
+ */
12
+ export declare function hashTrackingEvent(event: unknown): string;
13
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../../src/tracking/server/hash.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAExD"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Who is on the site right now. A process-local snapshot, not history: it is
3
+ * honestly empty after a restart until the first heartbeat, and a second
4
+ * process has its own.
5
+ */
6
+ export interface PresenceEntry<TExtra extends Record<string, unknown> = Record<string, unknown>> {
7
+ browserStreamId: string;
8
+ visitId: string | null;
9
+ ownerId: string | null;
10
+ page: string;
11
+ extra: TExtra;
12
+ }
13
+ export interface PresenceRegistry<TExtra extends Record<string, unknown>> {
14
+ touch(entry: PresenceEntry<TExtra>): void;
15
+ /** Everyone seen within the TTL, optionally filtered — a tenant, an area. */
16
+ snapshot(filter?: (entry: PresenceEntry<TExtra>) => boolean): Array<PresenceEntry<TExtra> & {
17
+ lastSeen: Date;
18
+ }>;
19
+ /** The most recently seen visit of one owner — for server-side events with no browser request. */
20
+ presentVisitOf(ownerId: string): string | null;
21
+ clear(): void;
22
+ }
23
+ export declare function createPresenceRegistry<TExtra extends Record<string, unknown>>(options?: {
24
+ ttlMs?: number;
25
+ now?: () => number;
26
+ }): PresenceRegistry<TExtra>;
27
+ //# sourceMappingURL=presence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../../../src/tracking/server/presence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAC5B,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEhE,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACtE,KAAK,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC1C,6EAA6E;IAC7E,QAAQ,CACN,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,OAAO,GACjD,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;IACrD,kGAAkG;IAClG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,sBAAsB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3E,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAO,GACnD,gBAAgB,CAAC,MAAM,CAAC,CAgC1B"}
@@ -0,0 +1,92 @@
1
+ import type { VisitBootstrapResponse, VisitEntryContext } from '../schemas.js';
2
+ /** Who is asking for the lease. */
3
+ export interface VisitActor {
4
+ /** The caller's identity, or `null` for an anonymous caller. */
5
+ ownerId: string | null;
6
+ userAgent?: string | null;
7
+ }
8
+ /** An active visit as the store reports it. */
9
+ export interface ActiveVisit {
10
+ id: string;
11
+ ownerId: string | null;
12
+ startedAt: Date;
13
+ }
14
+ /**
15
+ * The outbox health a bootstrap reports, written onto the visit so the
16
+ * server can see a browser whose queue is unavailable or overflowing.
17
+ */
18
+ export interface VisitOutboxHealth {
19
+ outboxState: VisitEntryContext['outboxState'];
20
+ outboxQueued: number;
21
+ outboxDropped: number;
22
+ outboxReportedAt: Date;
23
+ }
24
+ /**
25
+ * Which visits the caller may continue. `adopting`: an anonymous visit or the
26
+ * caller's own — the visit that started before sign-in is continued and
27
+ * adopted. `owned`: only the caller's own — every visitor already has an
28
+ * identity, an anonymous visit is never continued.
29
+ */
30
+ export type VisitOwnership = 'adopting' | 'owned';
31
+ export interface FindActiveVisitQuery {
32
+ browserStreamId: string;
33
+ /** A visit whose `lastActivityAt` is before this is not active. */
34
+ cutoff: Date;
35
+ actorOwnerId: string | null;
36
+ ownership: VisitOwnership;
37
+ /** The visit the browser believes it is in; preferred when still active. */
38
+ previousVisitId?: string;
39
+ }
40
+ /**
41
+ * The store the application implements over its database. Everything runs
42
+ * inside `withLineageLock`, which serialises bootstraps of one browser
43
+ * lineage — two tabs starting at once must not each open a visit.
44
+ */
45
+ export interface TrackingVisitStore<TTx = unknown> {
46
+ withLineageLock<T>(browserStreamId: string, fn: (tx: TTx) => Promise<T>): Promise<T>;
47
+ findActive(tx: TTx, query: FindActiveVisitQuery): Promise<ActiveVisit | null>;
48
+ /** Extend the lease; `health` is the browser's outbox report. */
49
+ touch(tx: TTx, visitId: string, now: Date, health: VisitOutboxHealth): Promise<void>;
50
+ /**
51
+ * Give an anonymous visit to the caller. Required under `ownership:
52
+ * 'adopting'` — `issueVisitLease` refuses to run without it rather than
53
+ * continue an anonymous visit and leave it anonymous; an `owned` store
54
+ * never adopts and may omit it.
55
+ */
56
+ adopt?(tx: TTx, visit: ActiveVisit, actorOwnerId: string, now: Date): Promise<void>;
57
+ /** Close every open visit of the lineage before a new one starts. */
58
+ endOpen(tx: TTx, browserStreamId: string, now: Date): Promise<void>;
59
+ /** Write a new visit; the application derives device, geo and source itself. */
60
+ create(tx: TTx, visit: {
61
+ id: string;
62
+ actor: VisitActor;
63
+ entry: VisitEntryContext;
64
+ startedAt: Date;
65
+ }, health: VisitOutboxHealth): Promise<void>;
66
+ }
67
+ export interface IssueVisitLeaseOptions {
68
+ ownership: VisitOwnership;
69
+ /** Idle time that ends a visit. Default 30 minutes. */
70
+ idleMs?: number;
71
+ now?: () => Date;
72
+ randomUUID?: () => string;
73
+ botPattern?: RegExp;
74
+ }
75
+ export interface IssuedVisitLease extends VisitBootstrapResponse {
76
+ /** `continued` when an active visit was extended, `started` when a new one opened. */
77
+ outcome: 'continued' | 'started' | 'bot';
78
+ /** The anonymous visit that was adopted by the caller, when one was. */
79
+ adopted: ActiveVisit | null;
80
+ }
81
+ /**
82
+ * Issue or renew a visit lease.
83
+ *
84
+ * A bot gets a lease that exists in no store: its later events are then
85
+ * `identity-invalid`, and neither the visit nor the events reach a report.
86
+ * Otherwise, under the lineage lock: the visit the browser names if it is
87
+ * still active and continuable, else the most recent active one; found —
88
+ * touch it (and adopt it when anonymous and the caller is identified); not
89
+ * found — end whatever is open and start a new one.
90
+ */
91
+ export declare function issueVisitLease<TTx>(store: TrackingVisitStore<TTx>, actor: VisitActor, entry: VisitEntryContext, { ownership, idleMs, now, randomUUID, botPattern, }: IssueVisitLeaseOptions): Promise<IssuedVisitLease>;
92
+ //# sourceMappingURL=visit-lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visit-lease.d.ts","sourceRoot":"","sources":["../../../src/tracking/server/visit-lease.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Visible time, measured additively.
3
+ *
4
+ * Every cut yields an interval with its own id and a duration since the last
5
+ * checkpoint; the server sums intervals by id, so a re-delivered event does not
6
+ * double-count and a heartbeat that never arrives loses only its own slice.
7
+ * The server dates the interval from its own clock and the duration; the
8
+ * client's `intervalStartedAt` is carried for the timeline, never trusted.
9
+ */
10
+ export interface VisibleInterval {
11
+ activeIntervalId: string;
12
+ activeDurationMs: number;
13
+ intervalStartedAt: number;
14
+ }
15
+ /** What a heartbeat carries: an interval while visible, only the fact while hidden. */
16
+ export type VisibleHeartbeat = (VisibleInterval & {
17
+ isVisible: true;
18
+ }) | {
19
+ isVisible: false;
20
+ activeDurationMs: 0;
21
+ };
22
+ export interface VisibleTimeMeter {
23
+ /** Restart the measurement — a new page, or the tab became visible again. */
24
+ checkpoint(): void;
25
+ /** Close the interval since the last checkpoint and start a new one. */
26
+ cut(): VisibleInterval;
27
+ /** A heartbeat's view: a cut while visible; while hidden, no interval at all. */
28
+ heartbeat(visible: boolean): VisibleHeartbeat;
29
+ }
30
+ export interface VisibleTimeMeterOptions {
31
+ /** Monotonic clock (default `performance.now`). */
32
+ now?: () => number;
33
+ /** Wall clock (default `Date.now`). */
34
+ wallClock?: () => number;
35
+ randomUUID?: () => string;
36
+ }
37
+ export declare function createVisibleTimeMeter(options?: VisibleTimeMeterOptions): VisibleTimeMeter;
38
+ //# sourceMappingURL=visible-time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visible-time.d.ts","sourceRoot":"","sources":["../../src/tracking/visible-time.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,uFAAuF;AACvF,MAAM,MAAM,gBAAgB,GACxB,CAAC,eAAe,GAAG;IAAE,SAAS,EAAE,IAAI,CAAA;CAAE,CAAC,GACvC;IAAE,SAAS,EAAE,KAAK,CAAC;IAAC,gBAAgB,EAAE,CAAC,CAAA;CAAE,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,UAAU,IAAI,IAAI,CAAC;IACnB,wEAAwE;IACxE,GAAG,IAAI,eAAe,CAAC;IACvB,iFAAiF;IACjF,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAAC;CAC/C;AAED,MAAM,WAAW,uBAAuB;IACtC,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC;CAC3B;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,uBAA4B,GACpC,gBAAgB,CAyBlB"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `stitchkit/tracking/server` — the decisions a tracking backend makes,
3
+ * without the storage it makes them over. The application reads visits and
4
+ * stored hashes from its own database, hands them here, and writes what comes
5
+ * back; `issueVisitLease` runs the visit algorithm over a store interface the
6
+ * application implements. No database, no schema, no domain. → ADR 0166.
7
+ */
8
+ export { type ActiveIntervalOptions, type ActiveTimeInterval, activeIntervalOf, } from './tracking/server/active-interval.js';
9
+ export { DEFAULT_BOT_USER_AGENT_PATTERN, isBotUserAgent } from './tracking/server/bot.js';
10
+ export { type DispositionEvent, type DispositionInput, type DispositionResult, dispositionTrackingBatch, type KnownVisit, } from './tracking/server/disposition.js';
11
+ export { hashTrackingEvent } from './tracking/server/hash.js';
12
+ export { createPresenceRegistry, type PresenceEntry, type PresenceRegistry, } from './tracking/server/presence.js';
13
+ export { type ActiveVisit, type FindActiveVisitQuery, type IssuedVisitLease, type IssueVisitLeaseOptions, issueVisitLease, type TrackingVisitStore, type VisitActor, type VisitOutboxHealth, type VisitOwnership, } from './tracking/server/visit-lease.js';
14
+ //# sourceMappingURL=tracking-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracking-server.d.ts","sourceRoot":"","sources":["../src/tracking-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,gBAAgB,GACjB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,8BAA8B,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,wBAAwB,EACxB,KAAK,UAAU,GAChB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EACL,sBAAsB,EACtB,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,173 @@
1
+ // src/tracking/server/active-interval.ts
2
+ var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3
+ function activeIntervalOf(event, serverNow, {
4
+ maxMs = 30 * 60 * 1000,
5
+ types = ["PAGE_LEAVE", "SESSION_HEARTBEAT"]
6
+ } = {}) {
7
+ if (!types.includes(event.type) || !event.metadata)
8
+ return null;
9
+ const intervalId = event.metadata.activeIntervalId;
10
+ const deltaMs = event.metadata.activeDurationMs;
11
+ if (typeof intervalId !== "string" || !UUID.test(intervalId))
12
+ return null;
13
+ if (typeof deltaMs !== "number" || !Number.isFinite(deltaMs))
14
+ return null;
15
+ const rounded = Math.round(deltaMs);
16
+ if (rounded <= 0 || rounded > maxMs)
17
+ return null;
18
+ return {
19
+ intervalId,
20
+ page: event.page,
21
+ deltaMs: rounded,
22
+ startedAt: new Date(serverNow.getTime() - rounded),
23
+ endedAt: serverNow
24
+ };
25
+ }
26
+ // src/tracking/server/bot.ts
27
+ var DEFAULT_BOT_USER_AGENT_PATTERN = /bot|crawl|spider|slurp|mediapartners|facebookexternalhit|bingpreview|yandex|baidu|duckduckbot|uptimerobot|pingdom|gtmetrix|pagespeed|lighthouse|headlesschrome/i;
28
+ function isBotUserAgent(userAgent, pattern = DEFAULT_BOT_USER_AGENT_PATTERN) {
29
+ return userAgent ? pattern.test(userAgent) : false;
30
+ }
31
+ // src/tracking/server/hash.ts
32
+ import { createHash } from "node:crypto";
33
+ function hashTrackingEvent(event) {
34
+ return createHash("sha256").update(JSON.stringify(event)).digest("hex");
35
+ }
36
+
37
+ // src/tracking/server/disposition.ts
38
+ function dispositionTrackingBatch({
39
+ events,
40
+ visits,
41
+ existing,
42
+ actorOwnerId,
43
+ userAgent,
44
+ botPattern = DEFAULT_BOT_USER_AGENT_PATTERN
45
+ }) {
46
+ if (isBotUserAgent(userAgent, botPattern)) {
47
+ return {
48
+ accepted: [],
49
+ dispositions: events.map((event) => ({
50
+ eventId: event.eventId,
51
+ status: "excluded-bot"
52
+ })),
53
+ conflicts: [],
54
+ adoptable: []
55
+ };
56
+ }
57
+ const visitsById = new Map(visits.map((visit) => [visit.id, visit]));
58
+ const accepted = [];
59
+ const dispositions = [];
60
+ const conflicts = [];
61
+ const adoptable = new Set;
62
+ const acceptedHashes = new Map;
63
+ for (const event of events) {
64
+ const visit = visitsById.get(event.visitId);
65
+ if (!visit || visit.browserStreamId !== event.browserStreamId || visit.ownerId !== null && visit.ownerId !== actorOwnerId) {
66
+ dispositions.push({ eventId: event.eventId, status: "identity-invalid" });
67
+ continue;
68
+ }
69
+ const stored = existing.get(event.eventId) ?? acceptedHashes.get(event.eventId);
70
+ if (stored !== undefined) {
71
+ if (stored !== hashTrackingEvent(event))
72
+ conflicts.push(event.eventId);
73
+ dispositions.push({ eventId: event.eventId, status: "duplicate" });
74
+ continue;
75
+ }
76
+ if (visit.ownerId === null && actorOwnerId)
77
+ adoptable.add(visit.id);
78
+ acceptedHashes.set(event.eventId, hashTrackingEvent(event));
79
+ accepted.push(event);
80
+ dispositions.push({ eventId: event.eventId, status: "accepted" });
81
+ }
82
+ return { accepted, dispositions, conflicts, adoptable: [...adoptable] };
83
+ }
84
+ // src/tracking/server/presence.ts
85
+ function createPresenceRegistry(options = {}) {
86
+ const ttlMs = options.ttlMs ?? 45000;
87
+ const now = options.now ?? (() => Date.now());
88
+ const active = new Map;
89
+ const sweep = () => {
90
+ const at = now();
91
+ for (const [key, entry] of active) {
92
+ if (at - entry.lastSeen > ttlMs)
93
+ active.delete(key);
94
+ }
95
+ };
96
+ return {
97
+ touch(entry) {
98
+ active.set(entry.browserStreamId, { ...entry, lastSeen: now() });
99
+ },
100
+ snapshot(filter = () => true) {
101
+ sweep();
102
+ return [...active.values()].filter(filter).map((entry) => ({ ...entry, lastSeen: new Date(entry.lastSeen) }));
103
+ },
104
+ presentVisitOf(ownerId) {
105
+ sweep();
106
+ let best = null;
107
+ for (const entry of active.values()) {
108
+ if (entry.ownerId !== ownerId)
109
+ continue;
110
+ if (!best || entry.lastSeen > best.lastSeen)
111
+ best = entry;
112
+ }
113
+ return best?.visitId ?? null;
114
+ },
115
+ clear: () => active.clear()
116
+ };
117
+ }
118
+ // src/tracking/server/visit-lease.ts
119
+ async function issueVisitLease(store, actor, entry, {
120
+ ownership,
121
+ idleMs = 30 * 60 * 1000,
122
+ now = () => new Date,
123
+ randomUUID = () => crypto.randomUUID(),
124
+ botPattern = DEFAULT_BOT_USER_AGENT_PATTERN
125
+ }) {
126
+ if (ownership === "adopting" && !store.adopt) {
127
+ throw new Error("issueVisitLease: ownership 'adopting' requires store.adopt");
128
+ }
129
+ const at = now();
130
+ const expiresAt = new Date(at.getTime() + idleMs).toISOString();
131
+ if (isBotUserAgent(actor.userAgent, botPattern)) {
132
+ return { visitId: randomUUID(), expiresAt, outcome: "bot", adopted: null };
133
+ }
134
+ const health = {
135
+ outboxState: entry.outboxState,
136
+ outboxQueued: entry.outboxQueued,
137
+ outboxDropped: entry.outboxDropped,
138
+ outboxReportedAt: at
139
+ };
140
+ return store.withLineageLock(entry.browserStreamId, async (tx) => {
141
+ const query = {
142
+ browserStreamId: entry.browserStreamId,
143
+ cutoff: new Date(at.getTime() - idleMs),
144
+ actorOwnerId: actor.ownerId,
145
+ ownership
146
+ };
147
+ const continuable = (visit) => visit && (visit.ownerId === actor.ownerId || visit.ownerId === null && ownership === "adopting") ? visit : null;
148
+ const requested = entry.previousVisitId ? continuable(await store.findActive(tx, { ...query, previousVisitId: entry.previousVisitId })) : null;
149
+ const active = requested ?? continuable(await store.findActive(tx, query));
150
+ if (active) {
151
+ let adopted = null;
152
+ if (ownership === "adopting" && active.ownerId === null && actor.ownerId && store.adopt) {
153
+ await store.adopt(tx, active, actor.ownerId, at);
154
+ adopted = active;
155
+ }
156
+ await store.touch(tx, active.id, at, health);
157
+ return { visitId: active.id, expiresAt, outcome: "continued", adopted };
158
+ }
159
+ await store.endOpen(tx, entry.browserStreamId, at);
160
+ const visitId = randomUUID();
161
+ await store.create(tx, { id: visitId, actor, entry, startedAt: at }, health);
162
+ return { visitId, expiresAt, outcome: "started", adopted: null };
163
+ });
164
+ }
165
+ export {
166
+ issueVisitLease,
167
+ isBotUserAgent,
168
+ hashTrackingEvent,
169
+ dispositionTrackingBatch,
170
+ createPresenceRegistry,
171
+ activeIntervalOf,
172
+ DEFAULT_BOT_USER_AGENT_PATTERN
173
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `stitchkit/tracking` — the browser mechanics of visitor tracking: a
3
+ * tab-shared outbox with reserved sequences and a short flush lease, delivery
4
+ * with one bounded retry, the page-leave beacon that actually arrives, visible
5
+ * time, scroll milestones, declarative clicks, attribution, and the client
6
+ * that composes them. No React, no DOM at import time, no event vocabulary of
7
+ * its own. The server half is `stitchkit/tracking/server`. → ADR 0166.
8
+ */
9
+ export { type AttributionStorage, parseReferrer, parseUtmFromSearch, type ReferrerRule, type ResolveAttributionInput, type ResolvedAttribution, resolveAttribution, } from './tracking/attribution.js';
10
+ export { sendUnloadBeacon } from './tracking/beacon.js';
11
+ export { type ClickTarget, type ResolveTrackedClickOptions, resolveTrackedClick, type TrackedClick, type TrackedClickAttributes, } from './tracking/clicks.js';
12
+ export { type BuiltinTrackingEventTypes, CONVENTIONAL_TRACKING_EVENT_TYPES, createTrackingClient, type EventsWithMetadata, type EventsWithoutMetadata, type TrackFn, type TrackingClient, type TrackingClientConfig, } from './tracking/client.js';
13
+ export { createTrackingContract, type TrackingContractConfig, type TrackingContractEndpoints, } from './tracking/contract.js';
14
+ export { deliverTrackingBatch, type TrackingDeliveryOptions, type TrackingDeliveryOutcome, } from './tracking/delivery.js';
15
+ export { browserTrackingHost, type TrackingHost, type TrackingPageContext, } from './tracking/host.js';
16
+ export { createOncePerPage, type OncePerPage } from './tracking/once-per-page.js';
17
+ export { createTrackingOutbox, type TrackingOutbox, type TrackingOutboxEvents, type TrackingOutboxHealth, type TrackingOutboxMeta, type TrackingOutboxOptions, type TrackingOutboxRecord, type TrackingOutboxStorage, type TrackingQueuedEvent, } from './tracking/outbox.js';
18
+ export { indexedDbOutboxStorage } from './tracking/outbox-storage-indexeddb.js';
19
+ export { memoryOutboxStorage } from './tracking/outbox-storage-memory.js';
20
+ export { type AttributionData, AttributionDataSchema, createTrackingSchemas, DEFAULT_BUILD_ID_PATTERN, type TrackEventsRequest, type TrackEventsResponse, TrackEventsResponseSchema, type TrackingDisposition, TrackingDispositionSchema, type TrackingDispositionStatus, TrackingDispositionStatusSchema, type TrackingEventEnvelope, type TrackingEventShape, type TrackingOutboxState, TrackingOutboxStateSchema, type TrackingSchemas, type TrackingSchemasConfig, type UtmData, UtmDataSchema, type VisitBootstrapResponse, VisitBootstrapResponseSchema, type VisitEntryContext, type VisitEntryContextShape, } from './tracking/schemas.js';
21
+ export { createScrollMilestones, type ScrollMilestones, scrollDepthPercent, } from './tracking/scroll.js';
22
+ export { createSequenceReserve, type SequenceReserve, type SequenceReserveOptions, } from './tracking/sequence-reserve.js';
23
+ export { createVisibleTimeMeter, type VisibleHeartbeat, type VisibleInterval, type VisibleTimeMeter, type VisibleTimeMeterOptions, } from './tracking/visible-time.js';
24
+ //# sourceMappingURL=tracking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracking.d.ts","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,KAAK,kBAAkB,EACvB,aAAa,EACb,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,yBAAyB,EAC9B,iCAAiC,EACjC,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,sBAAsB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,GAC/B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,oBAAoB,EACpB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EACL,KAAK,eAAe,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,KAAK,yBAAyB,EAC9B,+BAA+B,EAC/B,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,OAAO,EACZ,aAAa,EACb,KAAK,sBAAsB,EAC3B,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC5B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAC"}