@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.
- package/README.md +472 -0
- package/dist/core/context.d.ts +24 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +30 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/engine.d.ts +56 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +119 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/extensions.d.ts +33 -0
- package/dist/core/extensions.d.ts.map +1 -0
- package/dist/core/extensions.js +58 -0
- package/dist/core/extensions.js.map +1 -0
- package/dist/core/factory.d.ts +22 -5
- package/dist/core/factory.d.ts.map +1 -1
- package/dist/core/factory.js +231 -6
- package/dist/core/factory.js.map +1 -1
- package/dist/core/hooks.d.ts +32 -13
- package/dist/core/hooks.d.ts.map +1 -1
- package/dist/core/hooks.js +137 -15
- package/dist/core/hooks.js.map +1 -1
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/logger.d.ts +25 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +33 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/machine.d.ts +174 -0
- package/dist/core/machine.d.ts.map +1 -0
- package/dist/core/machine.js +228 -0
- package/dist/core/machine.js.map +1 -0
- package/dist/core/metric_metadata.d.ts +128 -0
- package/dist/core/metric_metadata.d.ts.map +1 -0
- package/dist/core/metric_metadata.js +47 -0
- package/dist/core/metric_metadata.js.map +1 -0
- package/dist/core/migrations.d.ts +52 -0
- package/dist/core/migrations.d.ts.map +1 -0
- package/dist/core/migrations.js +66 -0
- package/dist/core/migrations.js.map +1 -0
- package/dist/core/persistence.d.ts +50 -0
- package/dist/core/persistence.d.ts.map +1 -0
- package/dist/core/persistence.js +80 -0
- package/dist/core/persistence.js.map +1 -0
- package/dist/core/retention.d.ts +90 -0
- package/dist/core/retention.d.ts.map +1 -0
- package/dist/core/retention.js +119 -0
- package/dist/core/retention.js.map +1 -0
- package/dist/core/schemas.d.ts +35 -0
- package/dist/core/schemas.d.ts.map +1 -0
- package/dist/core/schemas.js +209 -0
- package/dist/core/schemas.js.map +1 -0
- package/dist/core/types.d.ts +10 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/warehouse.d.ts +58 -0
- package/dist/core/warehouse.d.ts.map +1 -0
- package/dist/core/warehouse.js +116 -0
- package/dist/core/warehouse.js.map +1 -0
- package/dist/rules/__fakes__/fakeClock.d.ts +7 -0
- package/dist/rules/__fakes__/fakeClock.d.ts.map +1 -0
- package/dist/rules/__fakes__/fakeClock.js +13 -0
- package/dist/rules/__fakes__/fakeClock.js.map +1 -0
- package/dist/rules/__fakes__/fakeEngine.d.ts +12 -0
- package/dist/rules/__fakes__/fakeEngine.d.ts.map +1 -0
- package/dist/rules/__fakes__/fakeEngine.js +33 -0
- package/dist/rules/__fakes__/fakeEngine.js.map +1 -0
- package/dist/rules/__fakes__/fakeStorage.d.ts +7 -0
- package/dist/rules/__fakes__/fakeStorage.d.ts.map +1 -0
- package/dist/rules/__fakes__/fakeStorage.js +22 -0
- package/dist/rules/__fakes__/fakeStorage.js.map +1 -0
- package/dist/rules/compiler-cache.d.ts +16 -0
- package/dist/rules/compiler-cache.d.ts.map +1 -0
- package/dist/rules/compiler-cache.js +29 -0
- package/dist/rules/compiler-cache.js.map +1 -0
- package/dist/rules/compiler.d.ts +27 -0
- package/dist/rules/compiler.d.ts.map +1 -0
- package/dist/rules/compiler.js +210 -0
- package/dist/rules/compiler.js.map +1 -0
- package/dist/rules/defaults/index.d.ts +13 -0
- package/dist/rules/defaults/index.d.ts.map +1 -0
- package/dist/rules/defaults/index.js +13 -0
- package/dist/rules/defaults/index.js.map +1 -0
- package/dist/rules/defaults/loader.d.ts +18 -0
- package/dist/rules/defaults/loader.d.ts.map +1 -0
- package/dist/rules/defaults/loader.js +37 -0
- package/dist/rules/defaults/loader.js.map +1 -0
- package/dist/rules/defaults/luminx.d.ts +6 -0
- package/dist/rules/defaults/luminx.d.ts.map +1 -0
- package/dist/rules/defaults/luminx.js +64 -0
- package/dist/rules/defaults/luminx.js.map +1 -0
- package/dist/rules/defaults/viva.d.ts +6 -0
- package/dist/rules/defaults/viva.d.ts.map +1 -0
- package/dist/rules/defaults/viva.js +45 -0
- package/dist/rules/defaults/viva.js.map +1 -0
- package/dist/rules/defaults/yogaring.d.ts +6 -0
- package/dist/rules/defaults/yogaring.d.ts.map +1 -0
- package/dist/rules/defaults/yogaring.js +45 -0
- package/dist/rules/defaults/yogaring.js.map +1 -0
- package/dist/rules/defaults/ziva.d.ts +10 -0
- package/dist/rules/defaults/ziva.d.ts.map +1 -0
- package/dist/rules/defaults/ziva.js +87 -0
- package/dist/rules/defaults/ziva.js.map +1 -0
- package/dist/rules/emitter.d.ts +20 -0
- package/dist/rules/emitter.d.ts.map +1 -0
- package/dist/rules/emitter.js +32 -0
- package/dist/rules/emitter.js.map +1 -0
- package/dist/rules/evaluator.d.ts +44 -0
- package/dist/rules/evaluator.d.ts.map +1 -0
- package/dist/rules/evaluator.js +127 -0
- package/dist/rules/evaluator.js.map +1 -0
- package/dist/rules/factory.d.ts +13 -0
- package/dist/rules/factory.d.ts.map +1 -0
- package/dist/rules/factory.js +56 -0
- package/dist/rules/factory.js.map +1 -0
- package/dist/rules/hooks/useRuleRegistry.d.ts +16 -0
- package/dist/rules/hooks/useRuleRegistry.d.ts.map +1 -0
- package/dist/rules/hooks/useRuleRegistry.js +26 -0
- package/dist/rules/hooks/useRuleRegistry.js.map +1 -0
- package/dist/rules/hooks/useRuleViolations.d.ts +21 -0
- package/dist/rules/hooks/useRuleViolations.d.ts.map +1 -0
- package/dist/rules/hooks/useRuleViolations.js +32 -0
- package/dist/rules/hooks/useRuleViolations.js.map +1 -0
- package/dist/rules/index.d.ts +30 -1
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +36 -1
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/registry.d.ts +32 -0
- package/dist/rules/registry.d.ts.map +1 -0
- package/dist/rules/registry.js +98 -0
- package/dist/rules/registry.js.map +1 -0
- package/dist/rules/schema.d.ts +221 -0
- package/dist/rules/schema.d.ts.map +1 -0
- package/dist/rules/schema.js +80 -0
- package/dist/rules/schema.js.map +1 -0
- package/dist/rules/throttle.d.ts +27 -0
- package/dist/rules/throttle.d.ts.map +1 -0
- package/dist/rules/throttle.js +76 -0
- package/dist/rules/throttle.js.map +1 -0
- package/dist/rules/types.d.ts +88 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +9 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/rules/validator.d.ts +27 -0
- package/dist/rules/validator.d.ts.map +1 -0
- package/dist/rules/validator.js +97 -0
- package/dist/rules/validator.js.map +1 -0
- package/dist/sync/buffer.d.ts +51 -0
- package/dist/sync/buffer.d.ts.map +1 -0
- package/dist/sync/buffer.js +188 -0
- package/dist/sync/buffer.js.map +1 -0
- package/dist/sync/context.d.ts +17 -0
- package/dist/sync/context.d.ts.map +1 -0
- package/dist/sync/context.js +23 -0
- package/dist/sync/context.js.map +1 -0
- package/dist/sync/errors.d.ts +19 -0
- package/dist/sync/errors.d.ts.map +1 -0
- package/dist/sync/errors.js +21 -0
- package/dist/sync/errors.js.map +1 -0
- package/dist/sync/events.d.ts +49 -0
- package/dist/sync/events.d.ts.map +1 -0
- package/dist/sync/events.js +46 -0
- package/dist/sync/events.js.map +1 -0
- package/dist/sync/factory.d.ts +65 -0
- package/dist/sync/factory.d.ts.map +1 -0
- package/dist/sync/factory.js +279 -0
- package/dist/sync/factory.js.map +1 -0
- package/dist/sync/fetcher.d.ts +74 -0
- package/dist/sync/fetcher.d.ts.map +1 -0
- package/dist/sync/fetcher.js +166 -0
- package/dist/sync/fetcher.js.map +1 -0
- package/dist/sync/flusher.d.ts +99 -0
- package/dist/sync/flusher.d.ts.map +1 -0
- package/dist/sync/flusher.js +246 -0
- package/dist/sync/flusher.js.map +1 -0
- package/dist/sync/hooks.d.ts +17 -0
- package/dist/sync/hooks.d.ts.map +1 -0
- package/dist/sync/hooks.js +48 -0
- package/dist/sync/hooks.js.map +1 -0
- package/dist/sync/index.d.ts +32 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +36 -1
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/manager.d.ts +48 -0
- package/dist/sync/manager.d.ts.map +1 -0
- package/dist/sync/manager.js +9 -0
- package/dist/sync/manager.js.map +1 -0
- package/dist/sync/mapper/activity.d.ts +31 -0
- package/dist/sync/mapper/activity.d.ts.map +1 -0
- package/dist/sync/mapper/activity.js +56 -0
- package/dist/sync/mapper/activity.js.map +1 -0
- package/dist/sync/mapper/battery.d.ts +12 -0
- package/dist/sync/mapper/battery.d.ts.map +1 -0
- package/dist/sync/mapper/battery.js +22 -0
- package/dist/sync/mapper/battery.js.map +1 -0
- package/dist/sync/mapper/firmware.d.ts +28 -0
- package/dist/sync/mapper/firmware.d.ts.map +1 -0
- package/dist/sync/mapper/firmware.js +43 -0
- package/dist/sync/mapper/firmware.js.map +1 -0
- package/dist/sync/mapper/heart-rate.d.ts +10 -0
- package/dist/sync/mapper/heart-rate.d.ts.map +1 -0
- package/dist/sync/mapper/heart-rate.js +19 -0
- package/dist/sync/mapper/heart-rate.js.map +1 -0
- package/dist/sync/mapper/hrv.d.ts +22 -0
- package/dist/sync/mapper/hrv.d.ts.map +1 -0
- package/dist/sync/mapper/hrv.js +56 -0
- package/dist/sync/mapper/hrv.js.map +1 -0
- package/dist/sync/mapper/ring-config.d.ts +33 -0
- package/dist/sync/mapper/ring-config.d.ts.map +1 -0
- package/dist/sync/mapper/ring-config.js +48 -0
- package/dist/sync/mapper/ring-config.js.map +1 -0
- package/dist/sync/mapper/sleep.d.ts +32 -0
- package/dist/sync/mapper/sleep.d.ts.map +1 -0
- package/dist/sync/mapper/sleep.js +103 -0
- package/dist/sync/mapper/sleep.js.map +1 -0
- package/dist/sync/mapper/spo2.d.ts +9 -0
- package/dist/sync/mapper/spo2.d.ts.map +1 -0
- package/dist/sync/mapper/spo2.js +18 -0
- package/dist/sync/mapper/spo2.js.map +1 -0
- package/dist/sync/mapper/temperature.d.ts +10 -0
- package/dist/sync/mapper/temperature.d.ts.map +1 -0
- package/dist/sync/mapper/temperature.js +19 -0
- package/dist/sync/mapper/temperature.js.map +1 -0
- package/dist/sync/mapper/time.d.ts +49 -0
- package/dist/sync/mapper/time.d.ts.map +1 -0
- package/dist/sync/mapper/time.js +107 -0
- package/dist/sync/mapper/time.js.map +1 -0
- package/dist/sync/mapper/types.d.ts +152 -0
- package/dist/sync/mapper/types.d.ts.map +1 -0
- package/dist/sync/mapper/types.js +15 -0
- package/dist/sync/mapper/types.js.map +1 -0
- package/dist/sync/overflow.d.ts +30 -0
- package/dist/sync/overflow.d.ts.map +1 -0
- package/dist/sync/overflow.js +114 -0
- package/dist/sync/overflow.js.map +1 -0
- package/dist/sync/pusher.d.ts +59 -0
- package/dist/sync/pusher.d.ts.map +1 -0
- package/dist/sync/pusher.js +115 -0
- package/dist/sync/pusher.js.map +1 -0
- package/dist/sync/scheduler.d.ts +84 -0
- package/dist/sync/scheduler.d.ts.map +1 -0
- package/dist/sync/scheduler.js +132 -0
- package/dist/sync/scheduler.js.map +1 -0
- package/dist/sync/triggers.d.ts +64 -0
- package/dist/sync/triggers.d.ts.map +1 -0
- package/dist/sync/triggers.js +113 -0
- package/dist/sync/triggers.js.map +1 -0
- package/dist/sync/types.d.ts +50 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +8 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/sync/watermark.d.ts +32 -0
- package/dist/sync/watermark.d.ts.map +1 -0
- package/dist/sync/watermark.js +61 -0
- package/dist/sync/watermark.js.map +1 -0
- package/dist/tools/__fakes__/engine.d.ts +25 -0
- package/dist/tools/__fakes__/engine.d.ts.map +1 -0
- package/dist/tools/__fakes__/engine.js +37 -0
- package/dist/tools/__fakes__/engine.js.map +1 -0
- package/dist/tools/audit.d.ts +31 -0
- package/dist/tools/audit.d.ts.map +1 -0
- package/dist/tools/audit.js +157 -0
- package/dist/tools/audit.js.map +1 -0
- package/dist/tools/authorize.d.ts +36 -0
- package/dist/tools/authorize.d.ts.map +1 -0
- package/dist/tools/authorize.js +87 -0
- package/dist/tools/authorize.js.map +1 -0
- package/dist/tools/budget.d.ts +15 -0
- package/dist/tools/budget.d.ts.map +1 -0
- package/dist/tools/budget.js +64 -0
- package/dist/tools/budget.js.map +1 -0
- package/dist/tools/factory.d.ts +43 -0
- package/dist/tools/factory.d.ts.map +1 -0
- package/dist/tools/factory.js +137 -0
- package/dist/tools/factory.js.map +1 -0
- package/dist/tools/formatters.d.ts +17 -0
- package/dist/tools/formatters.d.ts.map +1 -0
- package/dist/tools/formatters.js +30 -0
- package/dist/tools/formatters.js.map +1 -0
- package/dist/tools/impls/activity.d.ts +15 -0
- package/dist/tools/impls/activity.d.ts.map +1 -0
- package/dist/tools/impls/activity.js +61 -0
- package/dist/tools/impls/activity.js.map +1 -0
- package/dist/tools/impls/anomaly.d.ts +21 -0
- package/dist/tools/impls/anomaly.d.ts.map +1 -0
- package/dist/tools/impls/anomaly.js +70 -0
- package/dist/tools/impls/anomaly.js.map +1 -0
- package/dist/tools/impls/compare.d.ts +21 -0
- package/dist/tools/impls/compare.d.ts.map +1 -0
- package/dist/tools/impls/compare.js +68 -0
- package/dist/tools/impls/compare.js.map +1 -0
- package/dist/tools/impls/hrv.d.ts +15 -0
- package/dist/tools/impls/hrv.d.ts.map +1 -0
- package/dist/tools/impls/hrv.js +36 -0
- package/dist/tools/impls/hrv.js.map +1 -0
- package/dist/tools/impls/insights.d.ts +18 -0
- package/dist/tools/impls/insights.d.ts.map +1 -0
- package/dist/tools/impls/insights.js +41 -0
- package/dist/tools/impls/insights.js.map +1 -0
- package/dist/tools/impls/sleep.d.ts +15 -0
- package/dist/tools/impls/sleep.d.ts.map +1 -0
- package/dist/tools/impls/sleep.js +43 -0
- package/dist/tools/impls/sleep.js.map +1 -0
- package/dist/tools/index.d.ts +13 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +21 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mcp/adapter.d.ts +33 -0
- package/dist/tools/mcp/adapter.d.ts.map +1 -0
- package/dist/tools/mcp/adapter.js +56 -0
- package/dist/tools/mcp/adapter.js.map +1 -0
- package/dist/tools/mcp/guard.d.ts +17 -0
- package/dist/tools/mcp/guard.d.ts.map +1 -0
- package/dist/tools/mcp/guard.js +22 -0
- package/dist/tools/mcp/guard.js.map +1 -0
- package/dist/tools/mcp/index.d.ts +20 -0
- package/dist/tools/mcp/index.d.ts.map +1 -0
- package/dist/tools/mcp/index.js +16 -0
- package/dist/tools/mcp/index.js.map +1 -0
- package/dist/tools/mcp/server.d.ts +39 -0
- package/dist/tools/mcp/server.d.ts.map +1 -0
- package/dist/tools/mcp/server.js +70 -0
- package/dist/tools/mcp/server.js.map +1 -0
- package/dist/tools/mcp/transports/http.d.ts +54 -0
- package/dist/tools/mcp/transports/http.d.ts.map +1 -0
- package/dist/tools/mcp/transports/http.js +133 -0
- package/dist/tools/mcp/transports/http.js.map +1 -0
- package/dist/tools/mcp/transports/stdio.d.ts +22 -0
- package/dist/tools/mcp/transports/stdio.d.ts.map +1 -0
- package/dist/tools/mcp/transports/stdio.js +19 -0
- package/dist/tools/mcp/transports/stdio.js.map +1 -0
- package/dist/tools/rate-limit.d.ts +26 -0
- package/dist/tools/rate-limit.d.ts.map +1 -0
- package/dist/tools/rate-limit.js +67 -0
- package/dist/tools/rate-limit.js.map +1 -0
- package/dist/tools/types.d.ts +121 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +16 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/wrap.d.ts +53 -0
- package/dist/tools/wrap.d.ts.map +1 -0
- package/dist/tools/wrap.js +135 -0
- package/dist/tools/wrap.js.map +1 -0
- package/package.json +43 -16
- 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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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":"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"}
|
|
@@ -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"}
|