@mongrov/analytics 0.7.0 → 0.8.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.
- package/UPGRADING.md +86 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/migrations.d.ts.map +1 -1
- package/dist/core/migrations.js +39 -0
- package/dist/core/migrations.js.map +1 -1
- package/dist/core/sampling.d.ts +70 -0
- package/dist/core/sampling.d.ts.map +1 -0
- package/dist/core/sampling.js +107 -0
- package/dist/core/sampling.js.map +1 -0
- package/dist/core/schemas.d.ts.map +1 -1
- package/dist/core/schemas.js +6 -2
- package/dist/core/schemas.js.map +1 -1
- package/dist/rules/validator.d.ts.map +1 -1
- package/dist/rules/validator.js +35 -2
- package/dist/rules/validator.js.map +1 -1
- package/dist/sync/factory.d.ts +29 -4
- package/dist/sync/factory.d.ts.map +1 -1
- package/dist/sync/factory.js +37 -31
- package/dist/sync/factory.js.map +1 -1
- package/dist/sync/mapper/firmware.d.ts +3 -12
- package/dist/sync/mapper/firmware.d.ts.map +1 -1
- package/dist/sync/mapper/firmware.js +2 -8
- package/dist/sync/mapper/firmware.js.map +1 -1
- package/dist/sync/mapper/ring-config.d.ts +76 -28
- package/dist/sync/mapper/ring-config.d.ts.map +1 -1
- package/dist/sync/mapper/ring-config.js +118 -35
- package/dist/sync/mapper/ring-config.js.map +1 -1
- package/dist/sync/mapper/schema.d.ts +318 -60
- package/dist/sync/mapper/schema.d.ts.map +1 -1
- package/dist/sync/mapper/schema.js +40 -8
- package/dist/sync/mapper/schema.js.map +1 -1
- package/dist/sync/mapper/types.d.ts +52 -19
- package/dist/sync/mapper/types.d.ts.map +1 -1
- package/dist/sync/pending_closes.js +2 -2
- package/dist/sync/pending_closes.js.map +1 -1
- package/dist/sync/pusher.js +2 -2
- package/dist/sync/pusher.js.map +1 -1
- package/package.json +1 -1
package/UPGRADING.md
CHANGED
|
@@ -1,5 +1,91 @@
|
|
|
1
1
|
# Upgrading
|
|
2
2
|
|
|
3
|
+
## 0.7.0 → 0.8.0 — `device_config` firmware contract (Sprint 5 §2, T-02/T-09/T-10)
|
|
4
|
+
|
|
5
|
+
**Breaking, and it changes both a table and a mapper input type.**
|
|
6
|
+
|
|
7
|
+
### `device_config.data_type` → `device_config.metric`
|
|
8
|
+
|
|
9
|
+
Principle 21 says firmware enums must not reach the schema. The table now
|
|
10
|
+
stores our metric id:
|
|
11
|
+
|
|
12
|
+
```diff
|
|
13
|
+
- data_type INTEGER NOT NULL,
|
|
14
|
+
- PRIMARY KEY (device_id, data_type, valid_from)
|
|
15
|
+
+ metric VARCHAR NOT NULL,
|
|
16
|
+
+ PRIMARY KEY (device_id, metric, valid_from)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Migration **v5** converts existing rows using the JStyle automatic-monitoring
|
|
20
|
+
enum. Unknown codes are preserved as `unknown_<n>` rather than dropped, so a
|
|
21
|
+
firmware revision that added one stays diagnosable. Local catalog only — the
|
|
22
|
+
client never destructively rewrites the attached Iceberg zone.
|
|
23
|
+
|
|
24
|
+
**Update your `columnOrder`** for `device_config`: `data_type` → `metric`.
|
|
25
|
+
|
|
26
|
+
### `FirmwareMonitoringWindow` now matches the vendor struct
|
|
27
|
+
|
|
28
|
+
The previous type matched no vendor type — it had already discarded
|
|
29
|
+
`dataType`, which is why consumers had to supply a `RingConfigTranslator`
|
|
30
|
+
inventing the enum back from our own metric names.
|
|
31
|
+
|
|
32
|
+
```diff
|
|
33
|
+
-{ metric: string, interval_minutes: number, start_hour: number, end_hour: number }
|
|
34
|
+
+{ dataType: number, intervalTime: number,
|
|
35
|
+
+ startTime_Hour: number, startTime_Minutes: number,
|
|
36
|
+
+ endTime_Hour: number, endTime_Minutes: number,
|
|
37
|
+
+ weeks: { sunday: boolean, monday: boolean, Tuesday: boolean, ... },
|
|
38
|
+
+ mode?: number }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Verbatim from `AutomaticMonitoring_J2301A` (JStyle J2301A SDK). `dataType`
|
|
42
|
+
is **1 = heartRate, 2 = spo2, 3 = temperature, 4 = HRV**.
|
|
43
|
+
|
|
44
|
+
Note this is a **1:1 map**. The Sprint 5 spec described `dataType = 2` as
|
|
45
|
+
"spo2 + temperature (shared schedule)" needing a fan-out to two rows; the
|
|
46
|
+
SDK does not agree — temperature has its own code 3, so there is nothing to
|
|
47
|
+
fan out.
|
|
48
|
+
|
|
49
|
+
### New: `createSamplingResolver` (principle 22)
|
|
50
|
+
|
|
51
|
+
Chart rendering, gap detection and rule windows should derive cadence from
|
|
52
|
+
`device_config.interval_minutes`, not from constants — so a firmware
|
|
53
|
+
upgrade that changes sampling rate propagates without an app release.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { createSamplingResolver } from '@mongrov/analytics'
|
|
57
|
+
|
|
58
|
+
const sampling = createSamplingResolver({ analytics })
|
|
59
|
+
const { minutes, source } = await sampling.resolve('spo2', deviceId)
|
|
60
|
+
// source: 'device_config' when the ring reported a schedule,
|
|
61
|
+
// 'metric_metadata' before the first sync
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Memoized per `(deviceId, metric)` with a 10-minute TTL; call
|
|
65
|
+
`sampling.invalidate(deviceId)` after a sync that wrote a new config row.
|
|
66
|
+
Omitting `deviceId` returns the metadata fallback with no query, which is
|
|
67
|
+
what register-time rule validation uses.
|
|
68
|
+
|
|
69
|
+
`metric_metadata.sampling_minutes` stays as the fallback — it is what we
|
|
70
|
+
know before a device has ever reported.
|
|
71
|
+
|
|
72
|
+
### `ringConfigTranslator` is deprecated and ignored
|
|
73
|
+
|
|
74
|
+
The mapper reads the vendor struct directly and owns the translation.
|
|
75
|
+
|
|
76
|
+
```diff
|
|
77
|
+
createSyncManager({
|
|
78
|
+
…,
|
|
79
|
+
- ringConfigTranslator: myTranslator, // now ignored; delete it
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
It is no longer required when `tables` includes `device_config` — the Zod
|
|
84
|
+
refinement enforcing that is gone. The type is still exported for one
|
|
85
|
+
release so existing call sites compile.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
3
89
|
## 0.6.0 → 0.7.0 (Sprint 5 coordinated release)
|
|
4
90
|
|
|
5
91
|
This is a **coordinated release**. Upgrade all four together — the packages
|
package/dist/core/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export { createWatermarkCache, WATERMARK_CACHE_TTL_MS, } from './watermark-cache
|
|
|
19
19
|
export type { WatermarkCache, WatermarkCacheOptions, WatermarkCacheStats, } from './watermark-cache';
|
|
20
20
|
export { dismissInsight } from './insight';
|
|
21
21
|
export type { DismissInsightArgs, DismissInsightDeps } from './insight';
|
|
22
|
+
export { createSamplingResolver, fallbackSampling, minimumWindowMinutes, SAMPLING_CACHE_TTL_MS, } from './sampling';
|
|
23
|
+
export type { EffectiveSampling, SamplingResolver, SamplingResolverConfig, } from './sampling';
|
|
22
24
|
export { baselineAggregateFor, BASELINE_MIN_DAYS, BASELINE_WINDOW_DAYS, getBaselineMetricIds, } from './metric_metadata';
|
|
23
25
|
export type { BaselineDailyAggregate, BaselineWindowDays, } from './metric_metadata';
|
|
24
26
|
export { dropViewDdl, generateViewDdl, VIEWED_TABLES, watermarkColumnFor, } from './schemas';
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAG3C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACjE,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,YAAY,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAGvD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9D,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAKlD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAC5E,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAKzD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,WAAW,GACZ,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AAIxB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAG3C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACjE,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,YAAY,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAGvD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9D,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAKlD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAC5E,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAKzD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,WAAW,GACZ,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AAIxB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAKvE,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EACL,WAAW,EACX,eAAe,EACf,aAAa,EACb,kBAAkB,GACnB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG5C,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,aAAa,EACb,QAAQ,EACR,qBAAqB,EACrB,OAAO,EACP,WAAW,EACX,eAAe,EACf,OAAO,EACP,WAAW,EACX,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,GACZ,MAAM,SAAS,CAAA"}
|
package/dist/core/index.js
CHANGED
|
@@ -25,6 +25,10 @@ export { decodeDeviceEventPayload, DEVICE_EVENT_PAYLOAD_SCHEMAS, DEVICE_EVENT_TY
|
|
|
25
25
|
export { createWatermarkCache, WATERMARK_CACHE_TTL_MS, } from './watermark-cache';
|
|
26
26
|
// Insight dismissal (Sprint 5 §7b / T-15c).
|
|
27
27
|
export { dismissInsight } from './insight';
|
|
28
|
+
// Effective sampling cadence (Sprint 5 T-41, principle 22). Chart data
|
|
29
|
+
// providers and gap detection should resolve cadence through this rather
|
|
30
|
+
// than reading metric_metadata directly.
|
|
31
|
+
export { createSamplingResolver, fallbackSampling, minimumWindowMinutes, SAMPLING_CACHE_TTL_MS, } from './sampling';
|
|
28
32
|
// Baseline metadata (Sprint 5 §7).
|
|
29
33
|
export { baselineAggregateFor, BASELINE_MIN_DAYS, BASELINE_WINDOW_DAYS, getBaselineMetricIds, } from './metric_metadata';
|
|
30
34
|
// Union views (Sprint 5 §3). Registry/rule/tool SQL targets `v_{table}`,
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,kCAAkC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C,qBAAqB;AACrB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAOjE,qBAAqB;AACrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,SAAS;AACT,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAG9D,sEAAsE;AACtE,wEAAwE;AACxE,mDAAmD;AACnD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAG5E,sEAAsE;AACtE,oEAAoE;AACpE,8CAA8C;AAC9C,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,WAAW,GACZ,MAAM,iBAAiB,CAAA;AAOxB,2EAA2E;AAC3E,6DAA6D;AAC7D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,mBAAmB,CAAA;AAO1B,4CAA4C;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAG1C,mCAAmC;AACnC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAM1B,yEAAyE;AACzE,gEAAgE;AAChE,OAAO,EACL,WAAW,EACX,eAAe,EACf,aAAa,EACb,kBAAkB,GACnB,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,kCAAkC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C,qBAAqB;AACrB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAOjE,qBAAqB;AACrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,SAAS;AACT,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAG9D,sEAAsE;AACtE,wEAAwE;AACxE,mDAAmD;AACnD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAG5E,sEAAsE;AACtE,oEAAoE;AACpE,8CAA8C;AAC9C,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,WAAW,GACZ,MAAM,iBAAiB,CAAA;AAOxB,2EAA2E;AAC3E,6DAA6D;AAC7D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,mBAAmB,CAAA;AAO1B,4CAA4C;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAG1C,uEAAuE;AACvE,yEAAyE;AACzE,yCAAyC;AACzC,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,YAAY,CAAA;AAOnB,mCAAmC;AACnC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAM1B,yEAAyE;AACzE,gEAAgE;AAChE,OAAO,EACL,WAAW,EACX,eAAe,EACf,aAAa,EACb,kBAAkB,GACnB,MAAM,WAAW,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/core/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAA;IACb,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,YAAY,CAAA;AAEzC,MAAM,WAAW,SAAS;IACxB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACjE;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,SAAS,
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/core/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAA;IACb,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,YAAY,CAAA;AAEzC,MAAM,WAAW,SAAS;IACxB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACjE;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,SAAS,EAgKzC,CAAA;AAEF,uEAAuE;AACvE,eAAO,MAAM,eAAe,EAAE,MAA0B,CAAA;AAExD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExE;AAWD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;CACX;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,YAAY,EAChB,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,sBAAsB,CAAC,CAyCjC"}
|
package/dist/core/migrations.js
CHANGED
|
@@ -128,6 +128,45 @@ export const MIGRATIONS = Object.freeze([
|
|
|
128
128
|
await db.execute(qualifyDdl(LOCAL_SCHEMAS.user_baseline, 'user_baseline', catalogs.local));
|
|
129
129
|
},
|
|
130
130
|
},
|
|
131
|
+
{
|
|
132
|
+
version: 5,
|
|
133
|
+
name: 'device_config: data_type -> metric (Sprint 5 §2)',
|
|
134
|
+
// Principle 21 — firmware enums do not belong in the schema. Converts
|
|
135
|
+
// existing rows using the JStyle J2301A automatic-monitoring enum
|
|
136
|
+
// (1=heartRate, 2=spo2, 3=temperature, 4=HRV), which is what the old
|
|
137
|
+
// `data_type` column actually held.
|
|
138
|
+
//
|
|
139
|
+
// Numbered 5, not the spec's 2: versions 2-4 were spent before this
|
|
140
|
+
// landed (device_battery, insight v2, user_baseline).
|
|
141
|
+
//
|
|
142
|
+
// Idempotent: skips when `metric` already exists. Local only — the
|
|
143
|
+
// client never destructively rewrites the attached Iceberg catalog;
|
|
144
|
+
// remote schema evolution is a server-side operation.
|
|
145
|
+
async up(db, catalogs) {
|
|
146
|
+
const cols = await db.execute(`SELECT column_name FROM information_schema.columns `
|
|
147
|
+
+ `WHERE table_catalog = $catalog AND table_name = 'device_config'`, { catalog: catalogs.local });
|
|
148
|
+
if (cols.length === 0)
|
|
149
|
+
return; // table absent; baseline will create it
|
|
150
|
+
if (cols.some(c => c.column_name === 'metric'))
|
|
151
|
+
return;
|
|
152
|
+
await db.execute(`DROP TABLE IF EXISTS ${catalogs.local}.device_config_v2;`);
|
|
153
|
+
const tmpDdl = LOCAL_SCHEMAS.device_config.replace('CREATE TABLE device_config', `CREATE TABLE ${catalogs.local}.device_config_v2`);
|
|
154
|
+
await db.execute(tmpDdl);
|
|
155
|
+
await db.execute(`INSERT INTO ${catalogs.local}.device_config_v2 `
|
|
156
|
+
+ `(device_id, brand, family_id, user_id, metric, interval_minutes, `
|
|
157
|
+
+ `start_time, end_time, weeks, valid_from, valid_to) `
|
|
158
|
+
+ `SELECT device_id, brand, family_id, user_id, `
|
|
159
|
+
+ `CASE data_type WHEN 1 THEN 'heart_rate' WHEN 2 THEN 'spo2' `
|
|
160
|
+
+ `WHEN 3 THEN 'temperature' WHEN 4 THEN 'hrv' `
|
|
161
|
+
// Unknown codes are preserved rather than dropped, so a firmware
|
|
162
|
+
// revision that added one is diagnosable instead of invisible.
|
|
163
|
+
+ `ELSE 'unknown_' || data_type::VARCHAR END, `
|
|
164
|
+
+ `interval_minutes, start_time, end_time, weeks, valid_from, valid_to `
|
|
165
|
+
+ `FROM ${catalogs.local}.device_config;`);
|
|
166
|
+
await db.execute(`DROP TABLE ${catalogs.local}.device_config;`);
|
|
167
|
+
await db.execute(`ALTER TABLE ${catalogs.local}.device_config_v2 RENAME TO device_config;`);
|
|
168
|
+
},
|
|
169
|
+
},
|
|
131
170
|
]);
|
|
132
171
|
/** Version of the latest known migration — target for every attach. */
|
|
133
172
|
export const CURRENT_VERSION = MIGRATIONS.length;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/core/migrations.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/core/migrations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effective sampling cadence (Sprint 5 T-41, principle 22).
|
|
3
|
+
*
|
|
4
|
+
* > **Hardware-agnostic cadence.** Chart rendering, rule evaluation windows,
|
|
5
|
+
* > and gap detection derive sampling interval from
|
|
6
|
+
* > `device_config.interval_minutes`, never from constants.
|
|
7
|
+
*
|
|
8
|
+
* The point is that a firmware upgrade changing sampling rate should
|
|
9
|
+
* propagate to charts and rules without an app release. A chart that
|
|
10
|
+
* hard-codes "SpO₂ every 30 minutes" draws the wrong gaps the day a ring
|
|
11
|
+
* ships at 5-minute sampling; a rule whose window was sized against 30
|
|
12
|
+
* minutes silently stops being satisfiable.
|
|
13
|
+
*
|
|
14
|
+
* `metric_metadata.sampling_minutes` remains the fallback — it is what we
|
|
15
|
+
* know before a device has ever reported its schedule, which is every
|
|
16
|
+
* install until the first sync.
|
|
17
|
+
*
|
|
18
|
+
* ## Why this is a runtime read, not a constant
|
|
19
|
+
*
|
|
20
|
+
* `device_config` is SCD-2: one open row per (device, metric), with history.
|
|
21
|
+
* The effective cadence is therefore a property of a *device*, not of the
|
|
22
|
+
* metric, and two family members on one account can legitimately differ.
|
|
23
|
+
*
|
|
24
|
+
* ## Caching
|
|
25
|
+
*
|
|
26
|
+
* Memoized per `(deviceId, metric)`. Ring config changes rarely — it only
|
|
27
|
+
* moves when the user or firmware alters the schedule — so a long TTL is
|
|
28
|
+
* safe, and `invalidate()` covers the case where a sync just wrote a new
|
|
29
|
+
* config row.
|
|
30
|
+
*/
|
|
31
|
+
import { type MetricId, type MetricSamplingMinutes } from './metric_metadata';
|
|
32
|
+
import type { AnalyticsEngine, AnalyticsLogger } from './types';
|
|
33
|
+
/** Default memo lifetime. Ring schedules change on the order of never. */
|
|
34
|
+
export declare const SAMPLING_CACHE_TTL_MS: number;
|
|
35
|
+
export interface EffectiveSampling {
|
|
36
|
+
/** Minutes between samples, or `'per_session'` for sleep metrics. */
|
|
37
|
+
minutes: MetricSamplingMinutes;
|
|
38
|
+
/** Where the number came from — surfaced for diagnostics and tests. */
|
|
39
|
+
source: 'device_config' | 'metric_metadata';
|
|
40
|
+
}
|
|
41
|
+
export interface SamplingResolverConfig {
|
|
42
|
+
analytics: Pick<AnalyticsEngine, 'execute'>;
|
|
43
|
+
logger?: AnalyticsLogger;
|
|
44
|
+
ttlMs?: number;
|
|
45
|
+
now?: () => number;
|
|
46
|
+
}
|
|
47
|
+
export interface SamplingResolver {
|
|
48
|
+
/**
|
|
49
|
+
* Effective cadence for a metric on a device.
|
|
50
|
+
*
|
|
51
|
+
* Omitting `deviceId` returns the `metric_metadata` fallback without
|
|
52
|
+
* touching the database — the right behaviour for register-time
|
|
53
|
+
* validation, which runs before any device context exists.
|
|
54
|
+
*/
|
|
55
|
+
resolve(metric: MetricId, deviceId?: string): Promise<EffectiveSampling>;
|
|
56
|
+
/** Drop memoized entries for a device (all metrics), or everything. */
|
|
57
|
+
invalidate(deviceId?: string): void;
|
|
58
|
+
}
|
|
59
|
+
/** The fallback, with no I/O. */
|
|
60
|
+
export declare function fallbackSampling(metric: MetricId): EffectiveSampling;
|
|
61
|
+
export declare function createSamplingResolver(config: SamplingResolverConfig): SamplingResolver;
|
|
62
|
+
/**
|
|
63
|
+
* Minimum window, in minutes, that can hold `consecutive` samples at a
|
|
64
|
+
* given cadence. Used by the rules validator and by gap detection.
|
|
65
|
+
*
|
|
66
|
+
* `per_session` metrics return `null` — "consecutive nights" is bounded by
|
|
67
|
+
* the rule's window in days, not by a sampling interval.
|
|
68
|
+
*/
|
|
69
|
+
export declare function minimumWindowMinutes(sampling: MetricSamplingMinutes, consecutive: number): number | null;
|
|
70
|
+
//# sourceMappingURL=sampling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampling.d.ts","sourceRoot":"","sources":["../../src/core/sampling.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE/D,0EAA0E;AAC1E,eAAO,MAAM,qBAAqB,QAAiB,CAAA;AAEnD,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,OAAO,EAAE,qBAAqB,CAAA;IAC9B,uEAAuE;IACvE,MAAM,EAAE,eAAe,GAAG,iBAAiB,CAAA;CAC5C;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAA;IAC3C,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACxE,uEAAuE;IACvE,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC;AAWD,iCAAiC;AACjC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,iBAAiB,CAKpE;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,GAC7B,gBAAgB,CA2DlB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,qBAAqB,EAC/B,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAGf"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effective sampling cadence (Sprint 5 T-41, principle 22).
|
|
3
|
+
*
|
|
4
|
+
* > **Hardware-agnostic cadence.** Chart rendering, rule evaluation windows,
|
|
5
|
+
* > and gap detection derive sampling interval from
|
|
6
|
+
* > `device_config.interval_minutes`, never from constants.
|
|
7
|
+
*
|
|
8
|
+
* The point is that a firmware upgrade changing sampling rate should
|
|
9
|
+
* propagate to charts and rules without an app release. A chart that
|
|
10
|
+
* hard-codes "SpO₂ every 30 minutes" draws the wrong gaps the day a ring
|
|
11
|
+
* ships at 5-minute sampling; a rule whose window was sized against 30
|
|
12
|
+
* minutes silently stops being satisfiable.
|
|
13
|
+
*
|
|
14
|
+
* `metric_metadata.sampling_minutes` remains the fallback — it is what we
|
|
15
|
+
* know before a device has ever reported its schedule, which is every
|
|
16
|
+
* install until the first sync.
|
|
17
|
+
*
|
|
18
|
+
* ## Why this is a runtime read, not a constant
|
|
19
|
+
*
|
|
20
|
+
* `device_config` is SCD-2: one open row per (device, metric), with history.
|
|
21
|
+
* The effective cadence is therefore a property of a *device*, not of the
|
|
22
|
+
* metric, and two family members on one account can legitimately differ.
|
|
23
|
+
*
|
|
24
|
+
* ## Caching
|
|
25
|
+
*
|
|
26
|
+
* Memoized per `(deviceId, metric)`. Ring config changes rarely — it only
|
|
27
|
+
* moves when the user or firmware alters the schedule — so a long TTL is
|
|
28
|
+
* safe, and `invalidate()` covers the case where a sync just wrote a new
|
|
29
|
+
* config row.
|
|
30
|
+
*/
|
|
31
|
+
import { METRIC_METADATA, } from './metric_metadata';
|
|
32
|
+
/** Default memo lifetime. Ring schedules change on the order of never. */
|
|
33
|
+
export const SAMPLING_CACHE_TTL_MS = 10 * 60 * 1000;
|
|
34
|
+
/** The fallback, with no I/O. */
|
|
35
|
+
export function fallbackSampling(metric) {
|
|
36
|
+
return {
|
|
37
|
+
minutes: METRIC_METADATA[metric].sampling_minutes,
|
|
38
|
+
source: 'metric_metadata',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function createSamplingResolver(config) {
|
|
42
|
+
const ttlMs = config.ttlMs ?? SAMPLING_CACHE_TTL_MS;
|
|
43
|
+
const now = config.now ?? (() => Date.now());
|
|
44
|
+
const cache = new Map();
|
|
45
|
+
const keyOf = (deviceId, metric) => `${deviceId} ${metric}`;
|
|
46
|
+
return {
|
|
47
|
+
async resolve(metric, deviceId) {
|
|
48
|
+
// Register-time validation has no device. Returning the fallback here
|
|
49
|
+
// is deliberately permissive: a denser real device only ever makes a
|
|
50
|
+
// rule MORE satisfiable, never less, so validating against the
|
|
51
|
+
// nominal cadence cannot produce a false pass.
|
|
52
|
+
if (!deviceId)
|
|
53
|
+
return fallbackSampling(metric);
|
|
54
|
+
const key = keyOf(deviceId, metric);
|
|
55
|
+
const hit = cache.get(key);
|
|
56
|
+
if (hit && hit.expiresAt > now())
|
|
57
|
+
return hit.value;
|
|
58
|
+
let value = fallbackSampling(metric);
|
|
59
|
+
try {
|
|
60
|
+
const rows = await config.analytics.execute(`SELECT interval_minutes FROM device_config
|
|
61
|
+
WHERE device_id = $deviceId AND metric = $metric
|
|
62
|
+
AND valid_to IS NULL
|
|
63
|
+
ORDER BY valid_from DESC LIMIT 1`, { deviceId, metric });
|
|
64
|
+
const interval = rows[0]?.interval_minutes;
|
|
65
|
+
if (typeof interval === 'number' && interval > 0) {
|
|
66
|
+
value = { minutes: interval, source: 'device_config' };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
// A missing config row is normal (pre-first-sync). A failed read is
|
|
71
|
+
// not, but falling back beats failing a chart render or an
|
|
72
|
+
// evaluation pass over a cadence lookup.
|
|
73
|
+
config.logger?.warn('sampling: device_config read failed, using fallback', {
|
|
74
|
+
metric,
|
|
75
|
+
deviceId,
|
|
76
|
+
err: err.message,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
cache.set(key, { value, expiresAt: now() + ttlMs });
|
|
80
|
+
return value;
|
|
81
|
+
},
|
|
82
|
+
invalidate(deviceId) {
|
|
83
|
+
if (deviceId === undefined) {
|
|
84
|
+
cache.clear();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const prefix = `${deviceId} `;
|
|
88
|
+
for (const key of cache.keys()) {
|
|
89
|
+
if (key.startsWith(prefix))
|
|
90
|
+
cache.delete(key);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Minimum window, in minutes, that can hold `consecutive` samples at a
|
|
97
|
+
* given cadence. Used by the rules validator and by gap detection.
|
|
98
|
+
*
|
|
99
|
+
* `per_session` metrics return `null` — "consecutive nights" is bounded by
|
|
100
|
+
* the rule's window in days, not by a sampling interval.
|
|
101
|
+
*/
|
|
102
|
+
export function minimumWindowMinutes(sampling, consecutive) {
|
|
103
|
+
if (sampling === 'per_session')
|
|
104
|
+
return null;
|
|
105
|
+
return sampling * Math.max(1, consecutive);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=sampling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampling.js","sourceRoot":"","sources":["../../src/core/sampling.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/core/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,qEAAqE;AACrE,eAAO,MAAM,WAAW,uPAiBd,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,SAAS,CAEnD,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/core/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,qEAAqE;AACrE,eAAO,MAAM,WAAW,uPAiBd,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,SAAS,CAEnD,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CA4MtD,CAAA;AAEF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,wJAWhB,CAAA;AAEV,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAE7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GACrF,MAAM,CA0BR;AAkBD,iEAAiE;AACjE,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAI7D,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,YAAY,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAW,EACtD,IAAI,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACrC,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
package/dist/core/schemas.js
CHANGED
|
@@ -170,19 +170,23 @@ export const SCHEMAS = Object.freeze({
|
|
|
170
170
|
device_id VARCHAR NOT NULL,
|
|
171
171
|
battery_pct DOUBLE NOT NULL
|
|
172
172
|
) PARTITIONED BY (day(ts), device_id);`,
|
|
173
|
+
// Sprint 5 §2 — `metric VARCHAR`, not the firmware's `data_type` integer.
|
|
174
|
+
// Principle 21: firmware enums never leak into the schema. The mapper
|
|
175
|
+
// translates `dataType` (1=heartRate, 2=spo2, 3=temperature, 4=HRV per
|
|
176
|
+
// the JStyle J2301A SDK) at the ingestion boundary.
|
|
173
177
|
device_config: `CREATE TABLE device_config (
|
|
174
178
|
device_id VARCHAR NOT NULL,
|
|
175
179
|
brand VARCHAR NOT NULL,
|
|
176
180
|
family_id VARCHAR NOT NULL,
|
|
177
181
|
user_id VARCHAR NOT NULL,
|
|
178
|
-
|
|
182
|
+
metric VARCHAR NOT NULL,
|
|
179
183
|
interval_minutes INTEGER NOT NULL,
|
|
180
184
|
start_time VARCHAR,
|
|
181
185
|
end_time VARCHAR,
|
|
182
186
|
weeks INTEGER,
|
|
183
187
|
valid_from TIMESTAMP NOT NULL,
|
|
184
188
|
valid_to TIMESTAMP,
|
|
185
|
-
PRIMARY KEY (device_id,
|
|
189
|
+
PRIMARY KEY (device_id, metric, valid_from)
|
|
186
190
|
);`,
|
|
187
191
|
insight: `CREATE TABLE insight (
|
|
188
192
|
insight_id VARCHAR PRIMARY KEY,
|
package/dist/core/schemas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/core/schemas.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/core/schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/rules/validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/rules/validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,KAAK,IAAI,EAAuB,KAAK,MAAM,EAAW,MAAM,UAAU,CAAA;AA4B/E;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,CAS5D;AAgBD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CA4BnE;AAiGD,8EAA8E;AAC9E,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAOpE"}
|
package/dist/rules/validator.js
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* `RuleValidationError` whose message includes the metric's sampling
|
|
6
6
|
* cadence + the minimum viable window.
|
|
7
7
|
*/
|
|
8
|
+
import { isRegisteredKvKey, isRuleReadableKvKey, ruleReadableKvKeys, } from '@mongrov/types/kv-keys';
|
|
8
9
|
import { METRIC_METADATA } from '../core/metric_metadata';
|
|
10
|
+
import { minimumWindowMinutes } from '../core/sampling';
|
|
9
11
|
import { RuleValidationError, WINDOWS } from './schema';
|
|
10
12
|
/** Window durations in minutes. */
|
|
11
13
|
const WINDOW_MINUTES = {
|
|
@@ -67,6 +69,7 @@ function samplingLabel(metric) {
|
|
|
67
69
|
export function validateRule(rule, logger) {
|
|
68
70
|
validateConsecutive(rule);
|
|
69
71
|
validateContext(rule);
|
|
72
|
+
validateUserSettingKey(rule);
|
|
70
73
|
const allowed = allowedWindowsFor(rule.metric);
|
|
71
74
|
if (!allowed.includes(rule.window)) {
|
|
72
75
|
throw new RuleValidationError(`Rule ${rule.id}: metric ${rule.metric} sampled ${samplingLabel(rule.metric)}. `
|
|
@@ -116,9 +119,9 @@ function validateConsecutive(rule) {
|
|
|
116
119
|
// which the window already bounds.
|
|
117
120
|
return;
|
|
118
121
|
}
|
|
119
|
-
const needed = n
|
|
122
|
+
const needed = minimumWindowMinutes(cadence, n);
|
|
120
123
|
const available = WINDOW_MINUTES[rule.window];
|
|
121
|
-
if (needed > available) {
|
|
124
|
+
if (needed !== null && needed > available) {
|
|
122
125
|
throw new RuleValidationError(`Rule ${rule.id}: consecutive ${n} x ${cadence}min sampling needs `
|
|
123
126
|
+ `${needed}min but window ${rule.window} is only ${available}min. `
|
|
124
127
|
+ `The rule could never fire. Widen the window or lower consecutive.`);
|
|
@@ -140,6 +143,36 @@ function validateContext(rule) {
|
|
|
140
143
|
+ `${rule.metric} — it is already a per-session measure. Use context 'any'.`);
|
|
141
144
|
}
|
|
142
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Sprint 5 §4 / T-42 — a `user_setting` target's key must be in the
|
|
148
|
+
* KVStore namespace registry.
|
|
149
|
+
*
|
|
150
|
+
* Without this check a typo is invisible in the worst possible way: a rule
|
|
151
|
+
* pointing at `user:spo2SaveLevel` compiles, validates, evaluates, and
|
|
152
|
+
* silently uses its `defaultValue` forever. The user drags their safe
|
|
153
|
+
* level, sees it save, and the alert never changes behaviour — with no
|
|
154
|
+
* error raised anywhere. Failing at register() turns a silent
|
|
155
|
+
* misconfiguration into a loud one.
|
|
156
|
+
*
|
|
157
|
+
* UX-state keys are rejected too. They are in the registry so authors can
|
|
158
|
+
* see the whole namespace, but thresholding a rule on "did they dismiss a
|
|
159
|
+
* banner" is a bug rather than a feature.
|
|
160
|
+
*/
|
|
161
|
+
function validateUserSettingKey(rule) {
|
|
162
|
+
if (rule.target.type !== 'user_setting')
|
|
163
|
+
return;
|
|
164
|
+
const { key } = rule.target;
|
|
165
|
+
if (isRuleReadableKvKey(key))
|
|
166
|
+
return;
|
|
167
|
+
const known = ruleReadableKvKeys();
|
|
168
|
+
const detail = isRegisteredKvKey(key)
|
|
169
|
+
? `'${key}' is registered but is UX state, not a threshold`
|
|
170
|
+
: `'${key}' is not in the KVStore key namespace registry`;
|
|
171
|
+
throw new RuleValidationError(`Rule ${rule.id}: ${detail}. `
|
|
172
|
+
+ `Rule-readable keys are [${known.join(', ')}]. `
|
|
173
|
+
+ `Add new keys to KV_KEY_REGISTRY in @mongrov/types/kv-keys — a key `
|
|
174
|
+
+ `absent from the registry would silently fall back to defaultValue.`);
|
|
175
|
+
}
|
|
143
176
|
/** Scan a rawSql body for whole-word references to collected-only columns. */
|
|
144
177
|
export function referencedCollectedOnlyColumns(sql) {
|
|
145
178
|
const hits = new Set();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/rules/validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAiB,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/rules/validator.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/factory.d.ts
CHANGED
|
@@ -79,10 +79,11 @@ export interface CreateSyncManagerConfig {
|
|
|
79
79
|
computeBaselines?: boolean;
|
|
80
80
|
logger?: SchedulerLogger;
|
|
81
81
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* `
|
|
85
|
-
*
|
|
82
|
+
* @deprecated Ignored since Sprint 5 T-09/T-10. The mapper reads the
|
|
83
|
+
* vendor `AutomaticMonitoring_J2301A` struct directly and owns the
|
|
84
|
+
* `dataType` → metric translation, so no consumer-supplied bridge is
|
|
85
|
+
* needed. Accepted for one release so existing call sites keep
|
|
86
|
+
* compiling.
|
|
86
87
|
*/
|
|
87
88
|
ringConfigTranslator?: RingConfigTranslator;
|
|
88
89
|
}
|
|
@@ -91,4 +92,28 @@ export interface CreateSyncManagerConfig {
|
|
|
91
92
|
* malformed (e.g., missing columnOrder entries or negative row limits).
|
|
92
93
|
*/
|
|
93
94
|
export declare function createSyncManager(config: CreateSyncManagerConfig): SyncManager;
|
|
95
|
+
/**
|
|
96
|
+
* Pre-fetch the currently-open `device_config` rows for the given device
|
|
97
|
+
* so `mapRingConfig` can decide which metrics need SCD-2 closes.
|
|
98
|
+
*
|
|
99
|
+
* Value shape (`DeviceConfigRow`) is not consulted by the mapper — only
|
|
100
|
+
* `.has(dataType)` — but hydrating the row keeps the map future-friendly
|
|
101
|
+
* for logging / diagnostics without a second query.
|
|
102
|
+
*/
|
|
103
|
+
/**
|
|
104
|
+
* Open (`valid_to IS NULL`) device_config rows for one device.
|
|
105
|
+
*
|
|
106
|
+
* Fully-qualified `memory.main.device_config` so this resolves against the
|
|
107
|
+
* local catalog regardless of the active `USE <iceberg>.default` that
|
|
108
|
+
* `attach()` issues — a 2-part `main.device_config` would resolve against
|
|
109
|
+
* the current (Iceberg) catalog post-attach and miss.
|
|
110
|
+
*
|
|
111
|
+
* Exported so a test can execute it against the real DDL. It is
|
|
112
|
+
* hand-written SQL naming columns explicitly, which means a schema change
|
|
113
|
+
* can silently desync it: the 0.8.0 `data_type` -> `metric` rename did
|
|
114
|
+
* exactly that, and every unit test mocked the response so nothing caught
|
|
115
|
+
* it. `__tests__/prior-configs-sql.integration.test.ts` now runs it against
|
|
116
|
+
* a real table built from LOCAL_SCHEMAS.
|
|
117
|
+
*/
|
|
118
|
+
export declare const ACTIVE_PRIOR_CONFIGS_SQL: string;
|
|
94
119
|
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/sync/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAI5E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAI/C,OAAO,KAAK,EAIV,oBAAoB,EACrB,MAAM,gBAAgB,CAAA;AAIvB,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,eAAe,EAGrB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAc,WAAW,EAAkC,MAAM,WAAW,CAAA;AAExF,OAAO,KAAK,EAAe,cAAc,EAAe,MAAM,SAAS,CAAA;AAIvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/sync/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAI5E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAI/C,OAAO,KAAK,EAIV,oBAAoB,EACrB,MAAM,gBAAgB,CAAA;AAIvB,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,eAAe,EAGrB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAc,WAAW,EAAkC,MAAM,WAAW,CAAA;AAExF,OAAO,KAAK,EAAe,cAAc,EAAe,MAAM,SAAS,CAAA;AAIvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAkCjD,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,eAAe,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,aAAa,CAAA;IAClB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAA;IAC9C,cAAc,EAAE,cAAc,CAAA;IAC9B,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,cAAc,CAAC,EAAE,kBAAkB,CAAA;IACnC,WAAW,CAAC,EAAE,cAAc,CAAA;IAC5B,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,MAAM,CAAC,EAAE,cAAc,CAAA;KACxB,CAAA;IACD,SAAS,CAAC,EAAE;QACV,gBAAgB,CAAC,EAAE,OAAO,CAAA;QAC1B,YAAY,CAAC,EAAE,OAAO,CAAA;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;IACD;;;;;OAKG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB;;;;;;;;;OASG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACtE,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;CAC5C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,WAAW,CAmT9E;AAcD;;;;;;;GAOG;AACH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,QAOD,CAAA"}
|