@mongrov/analytics 0.1.0-alpha.0 → 0.1.0-alpha.10

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 (348) hide show
  1. package/README.md +472 -0
  2. package/dist/core/context.d.ts +24 -0
  3. package/dist/core/context.d.ts.map +1 -0
  4. package/dist/core/context.js +30 -0
  5. package/dist/core/context.js.map +1 -0
  6. package/dist/core/engine.d.ts +56 -0
  7. package/dist/core/engine.d.ts.map +1 -0
  8. package/dist/core/engine.js +119 -0
  9. package/dist/core/engine.js.map +1 -0
  10. package/dist/core/errors.d.ts +1 -1
  11. package/dist/core/errors.d.ts.map +1 -1
  12. package/dist/core/errors.js.map +1 -1
  13. package/dist/core/extensions.d.ts +33 -0
  14. package/dist/core/extensions.d.ts.map +1 -0
  15. package/dist/core/extensions.js +58 -0
  16. package/dist/core/extensions.js.map +1 -0
  17. package/dist/core/factory.d.ts +22 -5
  18. package/dist/core/factory.d.ts.map +1 -1
  19. package/dist/core/factory.js +231 -6
  20. package/dist/core/factory.js.map +1 -1
  21. package/dist/core/hooks.d.ts +32 -13
  22. package/dist/core/hooks.d.ts.map +1 -1
  23. package/dist/core/hooks.js +137 -15
  24. package/dist/core/hooks.js.map +1 -1
  25. package/dist/core/index.d.ts +3 -0
  26. package/dist/core/index.d.ts.map +1 -1
  27. package/dist/core/index.js +3 -1
  28. package/dist/core/index.js.map +1 -1
  29. package/dist/core/logger.d.ts +25 -0
  30. package/dist/core/logger.d.ts.map +1 -0
  31. package/dist/core/logger.js +33 -0
  32. package/dist/core/logger.js.map +1 -0
  33. package/dist/core/machine.d.ts +174 -0
  34. package/dist/core/machine.d.ts.map +1 -0
  35. package/dist/core/machine.js +228 -0
  36. package/dist/core/machine.js.map +1 -0
  37. package/dist/core/metric_metadata.d.ts +128 -0
  38. package/dist/core/metric_metadata.d.ts.map +1 -0
  39. package/dist/core/metric_metadata.js +47 -0
  40. package/dist/core/metric_metadata.js.map +1 -0
  41. package/dist/core/migrations.d.ts +52 -0
  42. package/dist/core/migrations.d.ts.map +1 -0
  43. package/dist/core/migrations.js +66 -0
  44. package/dist/core/migrations.js.map +1 -0
  45. package/dist/core/persistence.d.ts +50 -0
  46. package/dist/core/persistence.d.ts.map +1 -0
  47. package/dist/core/persistence.js +80 -0
  48. package/dist/core/persistence.js.map +1 -0
  49. package/dist/core/retention.d.ts +90 -0
  50. package/dist/core/retention.d.ts.map +1 -0
  51. package/dist/core/retention.js +119 -0
  52. package/dist/core/retention.js.map +1 -0
  53. package/dist/core/schemas.d.ts +35 -0
  54. package/dist/core/schemas.d.ts.map +1 -0
  55. package/dist/core/schemas.js +209 -0
  56. package/dist/core/schemas.js.map +1 -0
  57. package/dist/core/types.d.ts +10 -0
  58. package/dist/core/types.d.ts.map +1 -1
  59. package/dist/core/warehouse.d.ts +58 -0
  60. package/dist/core/warehouse.d.ts.map +1 -0
  61. package/dist/core/warehouse.js +116 -0
  62. package/dist/core/warehouse.js.map +1 -0
  63. package/dist/rules/__fakes__/fakeClock.d.ts +7 -0
  64. package/dist/rules/__fakes__/fakeClock.d.ts.map +1 -0
  65. package/dist/rules/__fakes__/fakeClock.js +13 -0
  66. package/dist/rules/__fakes__/fakeClock.js.map +1 -0
  67. package/dist/rules/__fakes__/fakeEngine.d.ts +12 -0
  68. package/dist/rules/__fakes__/fakeEngine.d.ts.map +1 -0
  69. package/dist/rules/__fakes__/fakeEngine.js +33 -0
  70. package/dist/rules/__fakes__/fakeEngine.js.map +1 -0
  71. package/dist/rules/__fakes__/fakeStorage.d.ts +7 -0
  72. package/dist/rules/__fakes__/fakeStorage.d.ts.map +1 -0
  73. package/dist/rules/__fakes__/fakeStorage.js +22 -0
  74. package/dist/rules/__fakes__/fakeStorage.js.map +1 -0
  75. package/dist/rules/compiler-cache.d.ts +16 -0
  76. package/dist/rules/compiler-cache.d.ts.map +1 -0
  77. package/dist/rules/compiler-cache.js +29 -0
  78. package/dist/rules/compiler-cache.js.map +1 -0
  79. package/dist/rules/compiler.d.ts +27 -0
  80. package/dist/rules/compiler.d.ts.map +1 -0
  81. package/dist/rules/compiler.js +210 -0
  82. package/dist/rules/compiler.js.map +1 -0
  83. package/dist/rules/defaults/index.d.ts +13 -0
  84. package/dist/rules/defaults/index.d.ts.map +1 -0
  85. package/dist/rules/defaults/index.js +13 -0
  86. package/dist/rules/defaults/index.js.map +1 -0
  87. package/dist/rules/defaults/loader.d.ts +18 -0
  88. package/dist/rules/defaults/loader.d.ts.map +1 -0
  89. package/dist/rules/defaults/loader.js +37 -0
  90. package/dist/rules/defaults/loader.js.map +1 -0
  91. package/dist/rules/defaults/luminx.d.ts +6 -0
  92. package/dist/rules/defaults/luminx.d.ts.map +1 -0
  93. package/dist/rules/defaults/luminx.js +64 -0
  94. package/dist/rules/defaults/luminx.js.map +1 -0
  95. package/dist/rules/defaults/viva.d.ts +6 -0
  96. package/dist/rules/defaults/viva.d.ts.map +1 -0
  97. package/dist/rules/defaults/viva.js +45 -0
  98. package/dist/rules/defaults/viva.js.map +1 -0
  99. package/dist/rules/defaults/yogaring.d.ts +6 -0
  100. package/dist/rules/defaults/yogaring.d.ts.map +1 -0
  101. package/dist/rules/defaults/yogaring.js +45 -0
  102. package/dist/rules/defaults/yogaring.js.map +1 -0
  103. package/dist/rules/defaults/ziva.d.ts +10 -0
  104. package/dist/rules/defaults/ziva.d.ts.map +1 -0
  105. package/dist/rules/defaults/ziva.js +87 -0
  106. package/dist/rules/defaults/ziva.js.map +1 -0
  107. package/dist/rules/emitter.d.ts +20 -0
  108. package/dist/rules/emitter.d.ts.map +1 -0
  109. package/dist/rules/emitter.js +32 -0
  110. package/dist/rules/emitter.js.map +1 -0
  111. package/dist/rules/evaluator.d.ts +44 -0
  112. package/dist/rules/evaluator.d.ts.map +1 -0
  113. package/dist/rules/evaluator.js +127 -0
  114. package/dist/rules/evaluator.js.map +1 -0
  115. package/dist/rules/factory.d.ts +13 -0
  116. package/dist/rules/factory.d.ts.map +1 -0
  117. package/dist/rules/factory.js +56 -0
  118. package/dist/rules/factory.js.map +1 -0
  119. package/dist/rules/hooks/useRuleRegistry.d.ts +16 -0
  120. package/dist/rules/hooks/useRuleRegistry.d.ts.map +1 -0
  121. package/dist/rules/hooks/useRuleRegistry.js +26 -0
  122. package/dist/rules/hooks/useRuleRegistry.js.map +1 -0
  123. package/dist/rules/hooks/useRuleViolations.d.ts +21 -0
  124. package/dist/rules/hooks/useRuleViolations.d.ts.map +1 -0
  125. package/dist/rules/hooks/useRuleViolations.js +32 -0
  126. package/dist/rules/hooks/useRuleViolations.js.map +1 -0
  127. package/dist/rules/index.d.ts +30 -1
  128. package/dist/rules/index.d.ts.map +1 -1
  129. package/dist/rules/index.js +36 -1
  130. package/dist/rules/index.js.map +1 -1
  131. package/dist/rules/registry.d.ts +32 -0
  132. package/dist/rules/registry.d.ts.map +1 -0
  133. package/dist/rules/registry.js +98 -0
  134. package/dist/rules/registry.js.map +1 -0
  135. package/dist/rules/schema.d.ts +221 -0
  136. package/dist/rules/schema.d.ts.map +1 -0
  137. package/dist/rules/schema.js +80 -0
  138. package/dist/rules/schema.js.map +1 -0
  139. package/dist/rules/throttle.d.ts +27 -0
  140. package/dist/rules/throttle.d.ts.map +1 -0
  141. package/dist/rules/throttle.js +76 -0
  142. package/dist/rules/throttle.js.map +1 -0
  143. package/dist/rules/types.d.ts +88 -0
  144. package/dist/rules/types.d.ts.map +1 -0
  145. package/dist/rules/types.js +9 -0
  146. package/dist/rules/types.js.map +1 -0
  147. package/dist/rules/validator.d.ts +27 -0
  148. package/dist/rules/validator.d.ts.map +1 -0
  149. package/dist/rules/validator.js +97 -0
  150. package/dist/rules/validator.js.map +1 -0
  151. package/dist/sync/buffer.d.ts +51 -0
  152. package/dist/sync/buffer.d.ts.map +1 -0
  153. package/dist/sync/buffer.js +188 -0
  154. package/dist/sync/buffer.js.map +1 -0
  155. package/dist/sync/context.d.ts +17 -0
  156. package/dist/sync/context.d.ts.map +1 -0
  157. package/dist/sync/context.js +23 -0
  158. package/dist/sync/context.js.map +1 -0
  159. package/dist/sync/errors.d.ts +19 -0
  160. package/dist/sync/errors.d.ts.map +1 -0
  161. package/dist/sync/errors.js +21 -0
  162. package/dist/sync/errors.js.map +1 -0
  163. package/dist/sync/events.d.ts +49 -0
  164. package/dist/sync/events.d.ts.map +1 -0
  165. package/dist/sync/events.js +46 -0
  166. package/dist/sync/events.js.map +1 -0
  167. package/dist/sync/factory.d.ts +65 -0
  168. package/dist/sync/factory.d.ts.map +1 -0
  169. package/dist/sync/factory.js +279 -0
  170. package/dist/sync/factory.js.map +1 -0
  171. package/dist/sync/fetcher.d.ts +74 -0
  172. package/dist/sync/fetcher.d.ts.map +1 -0
  173. package/dist/sync/fetcher.js +166 -0
  174. package/dist/sync/fetcher.js.map +1 -0
  175. package/dist/sync/flusher.d.ts +99 -0
  176. package/dist/sync/flusher.d.ts.map +1 -0
  177. package/dist/sync/flusher.js +246 -0
  178. package/dist/sync/flusher.js.map +1 -0
  179. package/dist/sync/hooks.d.ts +17 -0
  180. package/dist/sync/hooks.d.ts.map +1 -0
  181. package/dist/sync/hooks.js +48 -0
  182. package/dist/sync/hooks.js.map +1 -0
  183. package/dist/sync/index.d.ts +32 -1
  184. package/dist/sync/index.d.ts.map +1 -1
  185. package/dist/sync/index.js +36 -1
  186. package/dist/sync/index.js.map +1 -1
  187. package/dist/sync/manager.d.ts +48 -0
  188. package/dist/sync/manager.d.ts.map +1 -0
  189. package/dist/sync/manager.js +9 -0
  190. package/dist/sync/manager.js.map +1 -0
  191. package/dist/sync/mapper/activity.d.ts +31 -0
  192. package/dist/sync/mapper/activity.d.ts.map +1 -0
  193. package/dist/sync/mapper/activity.js +56 -0
  194. package/dist/sync/mapper/activity.js.map +1 -0
  195. package/dist/sync/mapper/battery.d.ts +12 -0
  196. package/dist/sync/mapper/battery.d.ts.map +1 -0
  197. package/dist/sync/mapper/battery.js +22 -0
  198. package/dist/sync/mapper/battery.js.map +1 -0
  199. package/dist/sync/mapper/firmware.d.ts +28 -0
  200. package/dist/sync/mapper/firmware.d.ts.map +1 -0
  201. package/dist/sync/mapper/firmware.js +43 -0
  202. package/dist/sync/mapper/firmware.js.map +1 -0
  203. package/dist/sync/mapper/heart-rate.d.ts +10 -0
  204. package/dist/sync/mapper/heart-rate.d.ts.map +1 -0
  205. package/dist/sync/mapper/heart-rate.js +19 -0
  206. package/dist/sync/mapper/heart-rate.js.map +1 -0
  207. package/dist/sync/mapper/hrv.d.ts +22 -0
  208. package/dist/sync/mapper/hrv.d.ts.map +1 -0
  209. package/dist/sync/mapper/hrv.js +56 -0
  210. package/dist/sync/mapper/hrv.js.map +1 -0
  211. package/dist/sync/mapper/ring-config.d.ts +33 -0
  212. package/dist/sync/mapper/ring-config.d.ts.map +1 -0
  213. package/dist/sync/mapper/ring-config.js +48 -0
  214. package/dist/sync/mapper/ring-config.js.map +1 -0
  215. package/dist/sync/mapper/sleep.d.ts +32 -0
  216. package/dist/sync/mapper/sleep.d.ts.map +1 -0
  217. package/dist/sync/mapper/sleep.js +103 -0
  218. package/dist/sync/mapper/sleep.js.map +1 -0
  219. package/dist/sync/mapper/spo2.d.ts +9 -0
  220. package/dist/sync/mapper/spo2.d.ts.map +1 -0
  221. package/dist/sync/mapper/spo2.js +18 -0
  222. package/dist/sync/mapper/spo2.js.map +1 -0
  223. package/dist/sync/mapper/temperature.d.ts +10 -0
  224. package/dist/sync/mapper/temperature.d.ts.map +1 -0
  225. package/dist/sync/mapper/temperature.js +19 -0
  226. package/dist/sync/mapper/temperature.js.map +1 -0
  227. package/dist/sync/mapper/time.d.ts +49 -0
  228. package/dist/sync/mapper/time.d.ts.map +1 -0
  229. package/dist/sync/mapper/time.js +107 -0
  230. package/dist/sync/mapper/time.js.map +1 -0
  231. package/dist/sync/mapper/types.d.ts +152 -0
  232. package/dist/sync/mapper/types.d.ts.map +1 -0
  233. package/dist/sync/mapper/types.js +15 -0
  234. package/dist/sync/mapper/types.js.map +1 -0
  235. package/dist/sync/overflow.d.ts +30 -0
  236. package/dist/sync/overflow.d.ts.map +1 -0
  237. package/dist/sync/overflow.js +114 -0
  238. package/dist/sync/overflow.js.map +1 -0
  239. package/dist/sync/pusher.d.ts +59 -0
  240. package/dist/sync/pusher.d.ts.map +1 -0
  241. package/dist/sync/pusher.js +115 -0
  242. package/dist/sync/pusher.js.map +1 -0
  243. package/dist/sync/scheduler.d.ts +84 -0
  244. package/dist/sync/scheduler.d.ts.map +1 -0
  245. package/dist/sync/scheduler.js +132 -0
  246. package/dist/sync/scheduler.js.map +1 -0
  247. package/dist/sync/triggers.d.ts +64 -0
  248. package/dist/sync/triggers.d.ts.map +1 -0
  249. package/dist/sync/triggers.js +113 -0
  250. package/dist/sync/triggers.js.map +1 -0
  251. package/dist/sync/types.d.ts +50 -0
  252. package/dist/sync/types.d.ts.map +1 -0
  253. package/dist/sync/types.js +8 -0
  254. package/dist/sync/types.js.map +1 -0
  255. package/dist/sync/watermark.d.ts +32 -0
  256. package/dist/sync/watermark.d.ts.map +1 -0
  257. package/dist/sync/watermark.js +61 -0
  258. package/dist/sync/watermark.js.map +1 -0
  259. package/dist/tools/__fakes__/engine.d.ts +25 -0
  260. package/dist/tools/__fakes__/engine.d.ts.map +1 -0
  261. package/dist/tools/__fakes__/engine.js +37 -0
  262. package/dist/tools/__fakes__/engine.js.map +1 -0
  263. package/dist/tools/audit.d.ts +31 -0
  264. package/dist/tools/audit.d.ts.map +1 -0
  265. package/dist/tools/audit.js +157 -0
  266. package/dist/tools/audit.js.map +1 -0
  267. package/dist/tools/authorize.d.ts +36 -0
  268. package/dist/tools/authorize.d.ts.map +1 -0
  269. package/dist/tools/authorize.js +87 -0
  270. package/dist/tools/authorize.js.map +1 -0
  271. package/dist/tools/budget.d.ts +15 -0
  272. package/dist/tools/budget.d.ts.map +1 -0
  273. package/dist/tools/budget.js +64 -0
  274. package/dist/tools/budget.js.map +1 -0
  275. package/dist/tools/factory.d.ts +43 -0
  276. package/dist/tools/factory.d.ts.map +1 -0
  277. package/dist/tools/factory.js +137 -0
  278. package/dist/tools/factory.js.map +1 -0
  279. package/dist/tools/formatters.d.ts +17 -0
  280. package/dist/tools/formatters.d.ts.map +1 -0
  281. package/dist/tools/formatters.js +30 -0
  282. package/dist/tools/formatters.js.map +1 -0
  283. package/dist/tools/impls/activity.d.ts +15 -0
  284. package/dist/tools/impls/activity.d.ts.map +1 -0
  285. package/dist/tools/impls/activity.js +61 -0
  286. package/dist/tools/impls/activity.js.map +1 -0
  287. package/dist/tools/impls/anomaly.d.ts +21 -0
  288. package/dist/tools/impls/anomaly.d.ts.map +1 -0
  289. package/dist/tools/impls/anomaly.js +70 -0
  290. package/dist/tools/impls/anomaly.js.map +1 -0
  291. package/dist/tools/impls/compare.d.ts +21 -0
  292. package/dist/tools/impls/compare.d.ts.map +1 -0
  293. package/dist/tools/impls/compare.js +68 -0
  294. package/dist/tools/impls/compare.js.map +1 -0
  295. package/dist/tools/impls/hrv.d.ts +15 -0
  296. package/dist/tools/impls/hrv.d.ts.map +1 -0
  297. package/dist/tools/impls/hrv.js +36 -0
  298. package/dist/tools/impls/hrv.js.map +1 -0
  299. package/dist/tools/impls/insights.d.ts +18 -0
  300. package/dist/tools/impls/insights.d.ts.map +1 -0
  301. package/dist/tools/impls/insights.js +41 -0
  302. package/dist/tools/impls/insights.js.map +1 -0
  303. package/dist/tools/impls/sleep.d.ts +15 -0
  304. package/dist/tools/impls/sleep.d.ts.map +1 -0
  305. package/dist/tools/impls/sleep.js +43 -0
  306. package/dist/tools/impls/sleep.js.map +1 -0
  307. package/dist/tools/index.d.ts +13 -1
  308. package/dist/tools/index.d.ts.map +1 -1
  309. package/dist/tools/index.js +21 -1
  310. package/dist/tools/index.js.map +1 -1
  311. package/dist/tools/mcp/adapter.d.ts +33 -0
  312. package/dist/tools/mcp/adapter.d.ts.map +1 -0
  313. package/dist/tools/mcp/adapter.js +56 -0
  314. package/dist/tools/mcp/adapter.js.map +1 -0
  315. package/dist/tools/mcp/guard.d.ts +17 -0
  316. package/dist/tools/mcp/guard.d.ts.map +1 -0
  317. package/dist/tools/mcp/guard.js +22 -0
  318. package/dist/tools/mcp/guard.js.map +1 -0
  319. package/dist/tools/mcp/index.d.ts +20 -0
  320. package/dist/tools/mcp/index.d.ts.map +1 -0
  321. package/dist/tools/mcp/index.js +16 -0
  322. package/dist/tools/mcp/index.js.map +1 -0
  323. package/dist/tools/mcp/server.d.ts +39 -0
  324. package/dist/tools/mcp/server.d.ts.map +1 -0
  325. package/dist/tools/mcp/server.js +70 -0
  326. package/dist/tools/mcp/server.js.map +1 -0
  327. package/dist/tools/mcp/transports/http.d.ts +54 -0
  328. package/dist/tools/mcp/transports/http.d.ts.map +1 -0
  329. package/dist/tools/mcp/transports/http.js +133 -0
  330. package/dist/tools/mcp/transports/http.js.map +1 -0
  331. package/dist/tools/mcp/transports/stdio.d.ts +22 -0
  332. package/dist/tools/mcp/transports/stdio.d.ts.map +1 -0
  333. package/dist/tools/mcp/transports/stdio.js +19 -0
  334. package/dist/tools/mcp/transports/stdio.js.map +1 -0
  335. package/dist/tools/rate-limit.d.ts +26 -0
  336. package/dist/tools/rate-limit.d.ts.map +1 -0
  337. package/dist/tools/rate-limit.js +67 -0
  338. package/dist/tools/rate-limit.js.map +1 -0
  339. package/dist/tools/types.d.ts +121 -0
  340. package/dist/tools/types.d.ts.map +1 -0
  341. package/dist/tools/types.js +16 -0
  342. package/dist/tools/types.js.map +1 -0
  343. package/dist/tools/wrap.d.ts +53 -0
  344. package/dist/tools/wrap.d.ts.map +1 -0
  345. package/dist/tools/wrap.js +135 -0
  346. package/dist/tools/wrap.js.map +1 -0
  347. package/package.json +43 -16
  348. package/LICENSE +0 -21
@@ -0,0 +1,37 @@
1
+ /**
2
+ * TOML catalog parser for brand default rules.
3
+ *
4
+ * A catalog is a TOML document with one or more `[[rule]]` array-of-tables
5
+ * entries; each entry is passed through `RuleSchema.safeParse` so bad
6
+ * catalogs fail at package load time with a precise message.
7
+ *
8
+ * The parser only wraps `@iarna/toml` — a TOML syntax error is rethrown as
9
+ * a `RuleValidationError` with a catalog-aware prefix so consumers can
10
+ * locate the offending brand file.
11
+ */
12
+ import TOML from '@iarna/toml';
13
+ import { RuleSchema, RuleValidationError } from '../schema';
14
+ export function parseCatalog(toml, options) {
15
+ const label = options?.name ?? 'catalog';
16
+ let doc;
17
+ try {
18
+ doc = TOML.parse(toml);
19
+ }
20
+ catch (err) {
21
+ throw new RuleValidationError(`${label}: TOML parse error — ${err.message}`);
22
+ }
23
+ const raw = doc.rule;
24
+ if (!Array.isArray(raw)) {
25
+ throw new RuleValidationError(`${label}: missing [[rule]] entries`);
26
+ }
27
+ const rules = [];
28
+ for (let i = 0; i < raw.length; i++) {
29
+ const parsed = RuleSchema.safeParse(raw[i]);
30
+ if (!parsed.success) {
31
+ throw new RuleValidationError(`${label}: rule ${i} invalid — ${parsed.error.message}`);
32
+ }
33
+ rules.push(parsed.data);
34
+ }
35
+ return rules;
36
+ }
37
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/rules/defaults/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,IAAI,MAAM,aAAa,CAAA;AAC9B,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAa,MAAM,WAAW,CAAA;AAWtE,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,OAA6B;IAE7B,MAAM,KAAK,GAAG,OAAO,EAAE,IAAI,IAAI,SAAS,CAAA;IACxC,IAAI,GAAe,CAAA;IACnB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAA;IACtC,CAAC;IACD,OAAO,GAAG,EAAE,CAAC;QACX,MAAM,IAAI,mBAAmB,CAC3B,GAAG,KAAK,wBAAyB,GAAa,CAAC,OAAO,EAAE,CACzD,CAAA;IACH,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAA;IACpB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,mBAAmB,CAC3B,GAAG,KAAK,4BAA4B,CACrC,CAAA;IACH,CAAC;IAED,MAAM,KAAK,GAAW,EAAE,CAAA;IACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,mBAAmB,CAC3B,GAAG,KAAK,UAAU,CAAC,cAAc,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CACxD,CAAA;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * LuminX brand default rules. Sidecar: `luminx.toml`.
3
+ */
4
+ import type { Rule } from '../schema';
5
+ export declare const luminxDefaults: Rule[];
6
+ //# sourceMappingURL=luminx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"luminx.d.ts","sourceRoot":"","sources":["../../../src/rules/defaults/luminx.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AA6DrC,eAAO,MAAM,cAAc,EAAE,IAAI,EAA2C,CAAA"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * LuminX brand default rules. Sidecar: `luminx.toml`.
3
+ */
4
+ import { parseCatalog } from './loader';
5
+ const TOML = `
6
+ [[rule]]
7
+ id = "luminx.battery-low"
8
+ brand = "luminx"
9
+ name = "LuminX battery low"
10
+ description = "Device battery below 15% in the past hour."
11
+ metric = "device_battery"
12
+ window = "1h"
13
+ aggregation = "last"
14
+ compare = "less_than"
15
+ severity = "warn"
16
+
17
+ [rule.target]
18
+ type = "absolute"
19
+ value = 15
20
+
21
+ [rule.throttle]
22
+ minGapMinutes = 240
23
+ maxPerDay = 3
24
+
25
+ [[rule]]
26
+ id = "luminx.battery-critical"
27
+ brand = "luminx"
28
+ name = "LuminX battery critical"
29
+ description = "Device battery below 5% — connectivity likely to drop."
30
+ metric = "device_battery"
31
+ window = "1h"
32
+ aggregation = "last"
33
+ compare = "less_than"
34
+ severity = "critical"
35
+
36
+ [rule.target]
37
+ type = "absolute"
38
+ value = 5
39
+
40
+ [rule.throttle]
41
+ minGapMinutes = 60
42
+ maxPerDay = 4
43
+
44
+ [[rule]]
45
+ id = "luminx.disconnect-24h"
46
+ brand = "luminx"
47
+ name = "LuminX disconnected"
48
+ description = "No device battery events observed in the past 24h."
49
+ metric = "device_battery"
50
+ window = "24h"
51
+ aggregation = "count"
52
+ compare = "equals"
53
+ severity = "warn"
54
+
55
+ [rule.target]
56
+ type = "absolute"
57
+ value = 0
58
+
59
+ [rule.throttle]
60
+ minGapMinutes = 720
61
+ maxPerDay = 1
62
+ `;
63
+ export const luminxDefaults = parseCatalog(TOML, { name: 'luminx' });
64
+ //# sourceMappingURL=luminx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"luminx.js","sourceRoot":"","sources":["../../../src/rules/defaults/luminx.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGvC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDZ,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAW,YAAY,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Viva brand default rules. Sidecar: `viva.toml`.
3
+ */
4
+ import type { Rule } from '../schema';
5
+ export declare const vivaDefaults: Rule[];
6
+ //# sourceMappingURL=viva.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viva.d.ts","sourceRoot":"","sources":["../../../src/rules/defaults/viva.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AA0CrC,eAAO,MAAM,YAAY,EAAE,IAAI,EAAyC,CAAA"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Viva brand default rules. Sidecar: `viva.toml`.
3
+ */
4
+ import { parseCatalog } from './loader';
5
+ const TOML = `
6
+ [[rule]]
7
+ id = "viva.battery-low"
8
+ brand = "viva"
9
+ name = "Viva battery low"
10
+ description = "Device battery below 20% in the past hour."
11
+ metric = "device_battery"
12
+ window = "1h"
13
+ aggregation = "last"
14
+ compare = "less_than"
15
+ severity = "warn"
16
+
17
+ [rule.target]
18
+ type = "absolute"
19
+ value = 20
20
+
21
+ [rule.throttle]
22
+ minGapMinutes = 360
23
+ maxPerDay = 2
24
+
25
+ [[rule]]
26
+ id = "viva.disconnect-24h"
27
+ brand = "viva"
28
+ name = "Viva disconnected"
29
+ description = "No device battery events observed in the past 24h."
30
+ metric = "device_battery"
31
+ window = "24h"
32
+ aggregation = "count"
33
+ compare = "equals"
34
+ severity = "warn"
35
+
36
+ [rule.target]
37
+ type = "absolute"
38
+ value = 0
39
+
40
+ [rule.throttle]
41
+ minGapMinutes = 720
42
+ maxPerDay = 1
43
+ `;
44
+ export const vivaDefaults = parseCatalog(TOML, { name: 'viva' });
45
+ //# sourceMappingURL=viva.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viva.js","sourceRoot":"","sources":["../../../src/rules/defaults/viva.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGvC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCZ,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAW,YAAY,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * YogaRing brand default rules. Sidecar: `yogaring.toml`.
3
+ */
4
+ import type { Rule } from '../schema';
5
+ export declare const yogaringDefaults: Rule[];
6
+ //# sourceMappingURL=yogaring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yogaring.d.ts","sourceRoot":"","sources":["../../../src/rules/defaults/yogaring.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AA0CrC,eAAO,MAAM,gBAAgB,EAAE,IAAI,EAA6C,CAAA"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * YogaRing brand default rules. Sidecar: `yogaring.toml`.
3
+ */
4
+ import { parseCatalog } from './loader';
5
+ const TOML = `
6
+ [[rule]]
7
+ id = "yogaring.stress-elevated"
8
+ brand = "yogaring"
9
+ name = "YogaRing stress nudge"
10
+ description = "Average stress score over 6h rose above 65."
11
+ metric = "stress"
12
+ window = "6h"
13
+ aggregation = "avg"
14
+ compare = "greater_than"
15
+ severity = "info"
16
+
17
+ [rule.target]
18
+ type = "absolute"
19
+ value = 65
20
+
21
+ [rule.throttle]
22
+ minGapMinutes = 240
23
+ maxPerDay = 2
24
+
25
+ [[rule]]
26
+ id = "yogaring.activity-low"
27
+ brand = "yogaring"
28
+ name = "YogaRing activity nudge"
29
+ description = "Daily step count is below 2500."
30
+ metric = "activity_steps"
31
+ window = "24h"
32
+ aggregation = "sum"
33
+ compare = "less_than"
34
+ severity = "info"
35
+
36
+ [rule.target]
37
+ type = "absolute"
38
+ value = 2500
39
+
40
+ [rule.throttle]
41
+ minGapMinutes = 720
42
+ maxPerDay = 1
43
+ `;
44
+ export const yogaringDefaults = parseCatalog(TOML, { name: 'yogaring' });
45
+ //# sourceMappingURL=yogaring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yogaring.js","sourceRoot":"","sources":["../../../src/rules/defaults/yogaring.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGvC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCZ,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAW,YAAY,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Ziva brand default rules.
3
+ *
4
+ * The template string below is a verbatim copy of `ziva.toml`. Edit the
5
+ * TOML sidecar, then either run `scripts/sync-toml.mjs` or copy-paste
6
+ * back into this literal. Metro/tsup do not read `.toml` files directly.
7
+ */
8
+ import type { Rule } from '../schema';
9
+ export declare const zivaDefaults: Rule[];
10
+ //# sourceMappingURL=ziva.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ziva.d.ts","sourceRoot":"","sources":["../../../src/rules/defaults/ziva.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAgFrC,eAAO,MAAM,YAAY,EAAE,IAAI,EAAyC,CAAA"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Ziva brand default rules.
3
+ *
4
+ * The template string below is a verbatim copy of `ziva.toml`. Edit the
5
+ * TOML sidecar, then either run `scripts/sync-toml.mjs` or copy-paste
6
+ * back into this literal. Metro/tsup do not read `.toml` files directly.
7
+ */
8
+ import { parseCatalog } from './loader';
9
+ const TOML = `
10
+ [[rule]]
11
+ id = "ziva.hrv-drop-30"
12
+ brand = "ziva"
13
+ name = "HRV drop below 30 ms"
14
+ description = "Average HRV over the last 24h fell below 30 ms."
15
+ metric = "hrv_ms"
16
+ window = "24h"
17
+ aggregation = "avg"
18
+ compare = "less_than"
19
+ severity = "warn"
20
+
21
+ [rule.target]
22
+ type = "absolute"
23
+ value = 30
24
+
25
+ [rule.throttle]
26
+ minGapMinutes = 360
27
+ maxPerDay = 2
28
+
29
+ [[rule]]
30
+ id = "ziva.sleep-deprivation-3d"
31
+ brand = "ziva"
32
+ name = "Sleep deprivation"
33
+ description = "Average nightly sleep across 3 nights below 360 minutes."
34
+ metric = "sleep_total_minutes"
35
+ window = "3d"
36
+ aggregation = "avg"
37
+ compare = "less_than"
38
+ severity = "warn"
39
+
40
+ [rule.target]
41
+ type = "absolute"
42
+ value = 360
43
+
44
+ [rule.throttle]
45
+ minGapMinutes = 720
46
+ maxPerDay = 1
47
+
48
+ [[rule]]
49
+ id = "ziva.stress-elevated"
50
+ brand = "ziva"
51
+ name = "Elevated stress"
52
+ description = "Average stress score over 6h rose above 70."
53
+ metric = "stress"
54
+ window = "6h"
55
+ aggregation = "avg"
56
+ compare = "greater_than"
57
+ severity = "info"
58
+
59
+ [rule.target]
60
+ type = "absolute"
61
+ value = 70
62
+
63
+ [rule.throttle]
64
+ minGapMinutes = 120
65
+ maxPerDay = 3
66
+
67
+ [[rule]]
68
+ id = "ziva.activity-low-24h"
69
+ brand = "ziva"
70
+ name = "Low activity"
71
+ description = "Daily step count is below 3000."
72
+ metric = "activity_steps"
73
+ window = "24h"
74
+ aggregation = "sum"
75
+ compare = "less_than"
76
+ severity = "info"
77
+
78
+ [rule.target]
79
+ type = "absolute"
80
+ value = 3000
81
+
82
+ [rule.throttle]
83
+ minGapMinutes = 720
84
+ maxPerDay = 1
85
+ `;
86
+ export const zivaDefaults = parseCatalog(TOML, { name: 'ziva' });
87
+ //# sourceMappingURL=ziva.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ziva.js","sourceRoot":"","sources":["../../../src/rules/defaults/ziva.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGvC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4EZ,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAW,YAAY,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Minimal typed event emitter for the rules engine.
3
+ *
4
+ * Only the `'violation'` event is supported. Handler exceptions are
5
+ * caught and logged so a single subscriber can't take down evaluation.
6
+ * `on(...)` returns an `Unsubscribe` closure per spec's public surface.
7
+ */
8
+ import type { Unsubscribe } from '../core/types';
9
+ import type { RuleViolation, RulesLogger } from './types';
10
+ type ViolationHandler = (v: RuleViolation) => void;
11
+ export interface RulesEmitter {
12
+ on(event: 'violation', handler: ViolationHandler): Unsubscribe;
13
+ emit(event: 'violation', payload: RuleViolation): void;
14
+ }
15
+ export interface CreateEmitterConfig {
16
+ logger?: RulesLogger;
17
+ }
18
+ export declare function createEmitter({ logger }?: CreateEmitterConfig): RulesEmitter;
19
+ export {};
20
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/rules/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAEzD,KAAK,gBAAgB,GAAG,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,CAAA;AAElD,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,GAAG,WAAW,CAAA;IAC9D,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAAA;CACvD;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,GAAE,mBAAwB,GAAG,YAAY,CAwBhF"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Minimal typed event emitter for the rules engine.
3
+ *
4
+ * Only the `'violation'` event is supported. Handler exceptions are
5
+ * caught and logged so a single subscriber can't take down evaluation.
6
+ * `on(...)` returns an `Unsubscribe` closure per spec's public surface.
7
+ */
8
+ export function createEmitter({ logger } = {}) {
9
+ const handlers = new Set();
10
+ return {
11
+ on(_event, handler) {
12
+ handlers.add(handler);
13
+ return () => {
14
+ handlers.delete(handler);
15
+ };
16
+ },
17
+ emit(_event, payload) {
18
+ for (const h of handlers) {
19
+ try {
20
+ h(payload);
21
+ }
22
+ catch (err) {
23
+ logger?.error('rules.emitter: violation handler threw', {
24
+ err: err.message,
25
+ ruleId: payload.ruleId,
26
+ });
27
+ }
28
+ }
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.js","sourceRoot":"","sources":["../../src/rules/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,UAAU,aAAa,CAAC,EAAE,MAAM,KAA0B,EAAE;IAChE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAA;IAE5C,OAAO;QACL,EAAE,CAAC,MAAM,EAAE,OAAO;YAChB,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACrB,OAAO,GAAG,EAAE;gBACV,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YAC1B,CAAC,CAAA;QACH,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,OAAO;YAClB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,CAAC,CAAC,OAAO,CAAC,CAAA;gBACZ,CAAC;gBACD,OAAO,GAAG,EAAE,CAAC;oBACX,MAAM,EAAE,KAAK,CAAC,wCAAwC,EAAE;wBACtD,GAAG,EAAG,GAAa,CAAC,OAAO;wBAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;qBACvB,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Rule evaluator — glues registry + compiler cache + throttle + emitter to
3
+ * `analytics.execute`.
4
+ *
5
+ * Two entry points:
6
+ * - `evaluateOnBatch(batch)` — called by sync after a successful flush.
7
+ * Considers only rules whose metric table intersects `batch.affectedTables`.
8
+ * - `evaluateScheduled()` — called by the sync scheduler cadence. Considers
9
+ * every active brand-matching rule, fanned out over family members.
10
+ *
11
+ * Both funnel through `evaluateRule(rule, ctx)` which is the throttle-gated
12
+ * single-user check. A returned `RuleViolation` is emitted synchronously via
13
+ * the shared emitter and echoed to callers.
14
+ *
15
+ * `analytics.execute` throws are caught + logged; a failing rule never
16
+ * blocks the rest of the pass.
17
+ */
18
+ import type { AnalyticsEngine } from '../core/types';
19
+ import type { CompilerCache } from './compiler-cache';
20
+ import type { createEmitter } from './emitter';
21
+ import type { RulesRegistry } from './registry';
22
+ import type { createThrottleStore } from './throttle';
23
+ import type { Clock, RuleViolation, RulesLogger, FlushSummary } from './types';
24
+ export interface EvaluatorConfig {
25
+ registry: RulesRegistry;
26
+ cache: CompilerCache;
27
+ throttle: ReturnType<typeof createThrottleStore>;
28
+ emitter: ReturnType<typeof createEmitter>;
29
+ analytics: AnalyticsEngine;
30
+ brand: string;
31
+ familyId: string;
32
+ familyMembersProvider: (ctx: {
33
+ brand: string;
34
+ familyId: string;
35
+ }) => Promise<string[]>;
36
+ clock: Clock;
37
+ logger?: RulesLogger;
38
+ }
39
+ export interface Evaluator {
40
+ evaluateOnBatch(batch: FlushSummary): Promise<RuleViolation[]>;
41
+ evaluateScheduled(): Promise<RuleViolation[]>;
42
+ }
43
+ export declare function createEvaluator(config: EvaluatorConfig): Evaluator;
44
+ //# sourceMappingURL=evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/rules/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,KAAK,EACV,KAAK,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACb,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,aAAa,CAAA;IACvB,KAAK,EAAE,aAAa,CAAA;IACpB,QAAQ,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA;IAChD,OAAO,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA;IACzC,SAAS,EAAE,eAAe,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,qBAAqB,EAAE,CAAC,GAAG,EAAE;QAC3B,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,MAAM,CAAA;KACjB,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACvB,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAOD,MAAM,WAAW,SAAS;IACxB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;IAC9D,iBAAiB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;CAC9C;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAkIlE"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Rule evaluator — glues registry + compiler cache + throttle + emitter to
3
+ * `analytics.execute`.
4
+ *
5
+ * Two entry points:
6
+ * - `evaluateOnBatch(batch)` — called by sync after a successful flush.
7
+ * Considers only rules whose metric table intersects `batch.affectedTables`.
8
+ * - `evaluateScheduled()` — called by the sync scheduler cadence. Considers
9
+ * every active brand-matching rule, fanned out over family members.
10
+ *
11
+ * Both funnel through `evaluateRule(rule, ctx)` which is the throttle-gated
12
+ * single-user check. A returned `RuleViolation` is emitted synchronously via
13
+ * the shared emitter and echoed to callers.
14
+ *
15
+ * `analytics.execute` throws are caught + logged; a failing rule never
16
+ * blocks the rest of the pass.
17
+ */
18
+ import { METRIC_METADATA } from '../core/metric_metadata';
19
+ export function createEvaluator(config) {
20
+ const { registry, cache, throttle, emitter, analytics, brand, familyId, familyMembersProvider, clock, logger, } = config;
21
+ async function evaluateRule(rule, ctx) {
22
+ const throttled = await throttle.isThrottled(rule.id, ctx.userId, rule.throttle);
23
+ if (throttled) {
24
+ logger?.debug('rules.evaluator: throttled', {
25
+ ruleId: rule.id,
26
+ userId: ctx.userId,
27
+ });
28
+ return null;
29
+ }
30
+ let rows;
31
+ try {
32
+ const compiled = cache.getCompiled(rule, registry.rev);
33
+ const params = {
34
+ userId: ctx.userId,
35
+ brand,
36
+ familyId: ctx.familyId,
37
+ ...compiled.params,
38
+ };
39
+ rows = await analytics.execute(compiled.sql, params);
40
+ }
41
+ catch (err) {
42
+ logger?.error('rules.evaluator: execute failed', {
43
+ ruleId: rule.id,
44
+ userId: ctx.userId,
45
+ err: err.message,
46
+ });
47
+ return null;
48
+ }
49
+ if (rows.length === 0) {
50
+ return null;
51
+ }
52
+ const row = rows[0];
53
+ const violation = {
54
+ ruleId: rule.id,
55
+ ruleName: rule.name,
56
+ severity: rule.severity,
57
+ userId: ctx.userId,
58
+ familyId: ctx.familyId,
59
+ brand: rule.brand ?? brand,
60
+ observedValue: Number(row.observed_value),
61
+ thresholdValue: Number(row.threshold_value),
62
+ observedAt: clock(),
63
+ evidence: {
64
+ metric: rule.metric,
65
+ window: rule.window,
66
+ aggregation: rule.aggregation,
67
+ compare: rule.compare,
68
+ target: rule.target,
69
+ },
70
+ };
71
+ await throttle.recordFire(rule.id, ctx.userId);
72
+ emitter.emit('violation', violation);
73
+ return violation;
74
+ }
75
+ function rulesForTables(rules, affectedTables) {
76
+ const tableSet = new Set(affectedTables);
77
+ return rules.filter((r) => {
78
+ const meta = METRIC_METADATA[r.metric];
79
+ return tableSet.has(meta.table);
80
+ });
81
+ }
82
+ return {
83
+ async evaluateOnBatch(batch) {
84
+ const active = registry.getByBrand(brand);
85
+ const relevant = rulesForTables(active, batch.affectedTables);
86
+ if (relevant.length === 0 || batch.affectedUserIds.length === 0) {
87
+ return [];
88
+ }
89
+ const violations = [];
90
+ for (const rule of relevant) {
91
+ for (const userId of batch.affectedUserIds) {
92
+ const v = await evaluateRule(rule, { userId, familyId });
93
+ if (v)
94
+ violations.push(v);
95
+ }
96
+ }
97
+ return violations;
98
+ },
99
+ async evaluateScheduled() {
100
+ const active = registry.getByBrand(brand);
101
+ if (active.length === 0) {
102
+ return [];
103
+ }
104
+ let members;
105
+ try {
106
+ members = await familyMembersProvider({ brand, familyId });
107
+ }
108
+ catch (err) {
109
+ logger?.error('rules.evaluator: familyMembersProvider failed', {
110
+ familyId,
111
+ err: err.message,
112
+ });
113
+ return [];
114
+ }
115
+ const violations = [];
116
+ for (const rule of active) {
117
+ for (const userId of members) {
118
+ const v = await evaluateRule(rule, { userId, familyId });
119
+ if (v)
120
+ violations.push(v);
121
+ }
122
+ }
123
+ return violations;
124
+ },
125
+ };
126
+ }
127
+ //# sourceMappingURL=evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../../src/rules/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,eAAe,EAAiB,MAAM,yBAAyB,CAAA;AAwCxE,MAAM,UAAU,eAAe,CAAC,MAAuB;IACrD,MAAM,EACJ,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,OAAO,EACP,SAAS,EACT,KAAK,EACL,QAAQ,EACR,qBAAqB,EACrB,KAAK,EACL,MAAM,GACP,GAAG,MAAM,CAAA;IAEV,KAAK,UAAU,YAAY,CACzB,IAAU,EACV,GAAyC;QAEzC,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAChF,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,EAAE,KAAK,CAAC,4BAA4B,EAAE;gBAC1C,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,MAAM,EAAE,GAAG,CAAC,MAAM;aACnB,CAAC,CAAA;YACF,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,IAAqB,CAAA;QACzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAA;YACtD,MAAM,MAAM,GAAG;gBACb,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK;gBACL,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,GAAG,QAAQ,CAAC,MAAM;aACnB,CAAA;YACD,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QACrE,CAAC;QACD,OAAO,GAAG,EAAE,CAAC;YACX,MAAM,EAAE,KAAK,CAAC,iCAAiC,EAAE;gBAC/C,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,GAAG,EAAG,GAAa,CAAC,OAAO;aAC5B,CAAC,CAAA;YACF,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,MAAM,SAAS,GAAkB;YAC/B,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,KAAK;YAC1B,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;YACzC,cAAc,EAAE,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC;YAC3C,UAAU,EAAE,KAAK,EAAE;YACnB,QAAQ,EAAE;gBACR,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB;SACF,CAAA;QAED,MAAM,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QAC9C,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;QACpC,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,SAAS,cAAc,CACrB,KAAa,EACb,cAA8C;QAE9C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS,cAAc,CAAC,CAAA;QAChD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACxB,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,MAAkB,CAAC,CAAA;YAClD,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjC,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,KAAK,CAAC,eAAe,CAAC,KAAK;YACzB,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YACzC,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,CAAA;YAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAChE,OAAO,EAAE,CAAA;YACX,CAAC;YACD,MAAM,UAAU,GAAoB,EAAE,CAAA;YACtC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;oBAC3C,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;oBACxD,IAAI,CAAC;wBAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBAC3B,CAAC;YACH,CAAC;YACD,OAAO,UAAU,CAAA;QACnB,CAAC;QAED,KAAK,CAAC,iBAAiB;YACrB,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YACzC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,EAAE,CAAA;YACX,CAAC;YACD,IAAI,OAAiB,CAAA;YACrB,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;YAC5D,CAAC;YACD,OAAO,GAAG,EAAE,CAAC;gBACX,MAAM,EAAE,KAAK,CAAC,+CAA+C,EAAE;oBAC7D,QAAQ;oBACR,GAAG,EAAG,GAAa,CAAC,OAAO;iBAC5B,CAAC,CAAA;gBACF,OAAO,EAAE,CAAA;YACX,CAAC;YACD,MAAM,UAAU,GAAoB,EAAE,CAAA;YACtC,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;gBAC1B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;oBAC7B,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;oBACxD,IAAI,CAAC;wBAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBAC3B,CAAC;YACH,CAAC;YACD,OAAO,UAAU,CAAA;QACnB,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `createRulesEngine(config)` — assembles registry, compiler cache,
3
+ * throttle store, emitter, and evaluator into the public `RulesEngine`
4
+ * surface.
5
+ *
6
+ * The factory holds no persistent state of its own; all state lives on
7
+ * the sub-modules. Callers pass a `KVStore` for durable state (rule
8
+ * enable flags, throttle counters) and an `AnalyticsEngine` for SQL
9
+ * execution.
10
+ */
11
+ import type { RulesEngine, RulesEngineConfig } from './types';
12
+ export declare function createRulesEngine(config: RulesEngineConfig): RulesEngine;
13
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/rules/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAE7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAiDxE"}