@mongrov/analytics 0.6.0 → 0.7.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/README.md +23 -10
- package/UPGRADING.md +370 -0
- package/dist/core/device-events.d.ts +14 -0
- package/dist/core/device-events.d.ts.map +1 -0
- package/dist/core/device-events.js +13 -0
- package/dist/core/device-events.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 +21 -4
- package/dist/core/extensions.d.ts.map +1 -1
- package/dist/core/extensions.js +21 -4
- package/dist/core/extensions.js.map +1 -1
- package/dist/core/factory.d.ts.map +1 -1
- package/dist/core/factory.js +125 -23
- package/dist/core/factory.js.map +1 -1
- package/dist/core/hooks.js +1 -1
- package/dist/core/hooks.js.map +1 -1
- package/dist/core/index.d.ts +11 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/insight.d.ts +44 -0
- package/dist/core/insight.d.ts.map +1 -0
- package/dist/core/insight.js +62 -0
- package/dist/core/insight.js.map +1 -0
- package/dist/core/metric_metadata.d.ts +55 -0
- package/dist/core/metric_metadata.d.ts.map +1 -1
- package/dist/core/metric_metadata.js +35 -7
- package/dist/core/metric_metadata.js.map +1 -1
- package/dist/core/migrations.d.ts.map +1 -1
- package/dist/core/migrations.js +64 -2
- package/dist/core/migrations.js.map +1 -1
- package/dist/core/retention.d.ts +44 -13
- package/dist/core/retention.d.ts.map +1 -1
- package/dist/core/retention.js +49 -22
- package/dist/core/retention.js.map +1 -1
- package/dist/core/schemas.d.ts +73 -2
- package/dist/core/schemas.d.ts.map +1 -1
- package/dist/core/schemas.js +154 -3
- package/dist/core/schemas.js.map +1 -1
- package/dist/core/table_metadata.d.ts.map +1 -1
- package/dist/core/table_metadata.js +3 -0
- package/dist/core/table_metadata.js.map +1 -1
- package/dist/core/types.d.ts +45 -10
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/warehouse.d.ts +28 -0
- package/dist/core/warehouse.d.ts.map +1 -1
- package/dist/core/warehouse.js +44 -0
- package/dist/core/warehouse.js.map +1 -1
- package/dist/core/watermark-cache.d.ts +75 -0
- package/dist/core/watermark-cache.d.ts.map +1 -0
- package/dist/core/watermark-cache.js +0 -0
- package/dist/core/watermark-cache.js.map +1 -0
- package/dist/rules/__fakes__/fakeEngine.d.ts +2 -0
- package/dist/rules/__fakes__/fakeEngine.d.ts.map +1 -1
- package/dist/rules/__fakes__/fakeEngine.js +4 -0
- package/dist/rules/__fakes__/fakeEngine.js.map +1 -1
- package/dist/rules/baseline-reader.d.ts +55 -0
- package/dist/rules/baseline-reader.d.ts.map +1 -0
- package/dist/rules/baseline-reader.js +111 -0
- package/dist/rules/baseline-reader.js.map +1 -0
- package/dist/rules/compiler.d.ts +36 -1
- package/dist/rules/compiler.d.ts.map +1 -1
- package/dist/rules/compiler.js +185 -39
- package/dist/rules/compiler.js.map +1 -1
- package/dist/rules/defaults/luminx.d.ts.map +1 -1
- package/dist/rules/defaults/luminx.js +8 -0
- package/dist/rules/defaults/luminx.js.map +1 -1
- package/dist/rules/defaults/viva.d.ts.map +1 -1
- package/dist/rules/defaults/viva.js +7 -0
- package/dist/rules/defaults/viva.js.map +1 -1
- package/dist/rules/defaults/yogaring.d.ts.map +1 -1
- package/dist/rules/defaults/yogaring.js +7 -0
- package/dist/rules/defaults/yogaring.js.map +1 -1
- package/dist/rules/defaults/ziva.d.ts.map +1 -1
- package/dist/rules/defaults/ziva.js +100 -24
- package/dist/rules/defaults/ziva.js.map +1 -1
- package/dist/rules/evaluator.d.ts +14 -3
- package/dist/rules/evaluator.d.ts.map +1 -1
- package/dist/rules/evaluator.js +157 -5
- package/dist/rules/evaluator.js.map +1 -1
- package/dist/rules/factory.d.ts.map +1 -1
- package/dist/rules/factory.js +5 -1
- package/dist/rules/factory.js.map +1 -1
- package/dist/rules/index.d.ts +2 -1
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +2 -1
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/schema.d.ts +75 -4
- package/dist/rules/schema.d.ts.map +1 -1
- package/dist/rules/schema.js +44 -0
- package/dist/rules/schema.js.map +1 -1
- package/dist/rules/types.d.ts +16 -1
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/validator.d.ts.map +1 -1
- package/dist/rules/validator.js +56 -0
- package/dist/rules/validator.js.map +1 -1
- package/dist/sync/baseline-compute.d.ts +63 -0
- package/dist/sync/baseline-compute.d.ts.map +1 -0
- package/dist/sync/baseline-compute.js +211 -0
- package/dist/sync/baseline-compute.js.map +1 -0
- package/dist/sync/events.d.ts +19 -5
- package/dist/sync/events.d.ts.map +1 -1
- package/dist/sync/events.js +17 -0
- package/dist/sync/events.js.map +1 -1
- package/dist/sync/factory.d.ts +25 -4
- package/dist/sync/factory.d.ts.map +1 -1
- package/dist/sync/factory.js +108 -15
- package/dist/sync/factory.js.map +1 -1
- package/dist/sync/fetcher.d.ts +15 -2
- package/dist/sync/fetcher.d.ts.map +1 -1
- package/dist/sync/fetcher.js +43 -7
- package/dist/sync/fetcher.js.map +1 -1
- package/dist/sync/flusher.d.ts +52 -2
- package/dist/sync/flusher.d.ts.map +1 -1
- package/dist/sync/flusher.js +78 -9
- package/dist/sync/flusher.js.map +1 -1
- package/dist/sync/index.d.ts +3 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +1 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/mapper/activity.d.ts.map +1 -1
- package/dist/sync/mapper/activity.js +2 -1
- package/dist/sync/mapper/activity.js.map +1 -1
- package/dist/sync/mapper/ring-config.js +1 -1
- package/dist/sync/mapper/ring-config.js.map +1 -1
- package/dist/sync/mapper/schema.d.ts +411 -0
- package/dist/sync/mapper/schema.d.ts.map +1 -0
- package/dist/sync/mapper/schema.js +128 -0
- package/dist/sync/mapper/schema.js.map +1 -0
- package/dist/sync/mapper/sleep.d.ts +58 -13
- package/dist/sync/mapper/sleep.d.ts.map +1 -1
- package/dist/sync/mapper/sleep.js +141 -44
- package/dist/sync/mapper/sleep.js.map +1 -1
- package/dist/sync/mapper/types.d.ts +66 -10
- package/dist/sync/mapper/types.d.ts.map +1 -1
- package/dist/sync/scheduler.d.ts +7 -0
- package/dist/sync/scheduler.d.ts.map +1 -1
- package/dist/sync/scheduler.js +14 -0
- package/dist/sync/scheduler.js.map +1 -1
- package/dist/tools/__fakes__/engine.d.ts +2 -0
- package/dist/tools/__fakes__/engine.d.ts.map +1 -1
- package/dist/tools/__fakes__/engine.js +10 -0
- package/dist/tools/__fakes__/engine.js.map +1 -1
- package/dist/tools/authorize.d.ts +19 -12
- package/dist/tools/authorize.d.ts.map +1 -1
- package/dist/tools/authorize.js +31 -40
- package/dist/tools/authorize.js.map +1 -1
- package/dist/tools/factory.d.ts +2 -0
- package/dist/tools/factory.d.ts.map +1 -1
- package/dist/tools/factory.js +12 -1
- package/dist/tools/factory.js.map +1 -1
- package/dist/tools/formatters/copy-guidelines.d.ts +57 -0
- package/dist/tools/formatters/copy-guidelines.d.ts.map +1 -0
- package/dist/tools/formatters/copy-guidelines.js +110 -0
- package/dist/tools/formatters/copy-guidelines.js.map +1 -0
- package/dist/tools/formatters/index.d.ts +14 -0
- package/dist/tools/formatters/index.d.ts.map +1 -0
- package/dist/tools/formatters/index.js +14 -0
- package/dist/tools/formatters/index.js.map +1 -0
- package/dist/tools/formatters/spo2.d.ts +21 -0
- package/dist/tools/formatters/spo2.d.ts.map +1 -0
- package/dist/tools/formatters/spo2.js +79 -0
- package/dist/tools/formatters/spo2.js.map +1 -0
- package/dist/tools/{formatters.d.ts → formatters/text.d.ts} +1 -1
- package/dist/tools/formatters/text.d.ts.map +1 -0
- package/dist/tools/{formatters.js → formatters/text.js} +1 -1
- package/dist/tools/formatters/text.js.map +1 -0
- package/dist/tools/impls/activity.d.ts +2 -2
- package/dist/tools/impls/activity.js +7 -3
- package/dist/tools/impls/activity.js.map +1 -1
- package/dist/tools/impls/anomaly.d.ts +2 -2
- package/dist/tools/impls/anomaly.js +8 -4
- package/dist/tools/impls/anomaly.js.map +1 -1
- package/dist/tools/impls/compare.d.ts +2 -2
- package/dist/tools/impls/compare.js +8 -4
- package/dist/tools/impls/compare.js.map +1 -1
- package/dist/tools/impls/hrv.d.ts +2 -2
- package/dist/tools/impls/hrv.js +6 -2
- package/dist/tools/impls/hrv.js.map +1 -1
- package/dist/tools/impls/insights.d.ts +4 -4
- package/dist/tools/impls/insights.d.ts.map +1 -1
- package/dist/tools/impls/insights.js +10 -3
- package/dist/tools/impls/insights.js.map +1 -1
- package/dist/tools/impls/sleep.d.ts +2 -2
- package/dist/tools/impls/sleep.js +6 -2
- package/dist/tools/impls/sleep.js.map +1 -1
- package/dist/tools/impls/spo2.d.ts +52 -0
- package/dist/tools/impls/spo2.d.ts.map +1 -0
- package/dist/tools/impls/spo2.js +65 -0
- package/dist/tools/impls/spo2.js.map +1 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mcp/guard.d.ts +28 -11
- package/dist/tools/mcp/guard.d.ts.map +1 -1
- package/dist/tools/mcp/guard.js +45 -15
- package/dist/tools/mcp/guard.js.map +1 -1
- package/dist/tools/mcp/index.d.ts +1 -1
- package/dist/tools/mcp/index.d.ts.map +1 -1
- package/dist/tools/mcp/index.js +1 -1
- package/dist/tools/mcp/index.js.map +1 -1
- package/dist/tools/mcp/server.d.ts.map +1 -1
- package/dist/tools/mcp/server.js +4 -0
- package/dist/tools/mcp/server.js.map +1 -1
- package/dist/tools/mcp/transports/http.d.ts.map +1 -1
- package/dist/tools/mcp/transports/http.js +4 -0
- package/dist/tools/mcp/transports/http.js.map +1 -1
- package/package.json +8 -5
- package/dist/tools/formatters.d.ts.map +0 -1
- package/dist/tools/formatters.js.map +0 -1
|
@@ -2,43 +2,98 @@
|
|
|
2
2
|
* Sleep reconstruction mapper (T-06).
|
|
3
3
|
*
|
|
4
4
|
* Firmware `sleep_processed` emits per-block rows tagged with a `start`
|
|
5
|
-
* (session start), `end
|
|
6
|
-
* `confidence` (0..1), and per-block `timestamp` (block instant).
|
|
7
|
-
* blocks share the same `start` when they belong to the same
|
|
5
|
+
* (session start), `end` (session end), `block_type` (primary / light / deep /
|
|
6
|
+
* rem / awake), `confidence` (0..1), and per-block `timestamp` (block instant).
|
|
7
|
+
* Multiple blocks share the same `start` when they belong to the same session.
|
|
8
8
|
*
|
|
9
9
|
* Reconstruction rules (spec.md §Firmware mapper + tasks.md T-06):
|
|
10
10
|
* - Group rows by `start`.
|
|
11
11
|
* - A session is included if AT LEAST ONE block in the group has
|
|
12
12
|
* `block_type === 'primary'` AND `confidence >= 0.7`. This filters
|
|
13
13
|
* day-time naps and low-confidence noise.
|
|
14
|
-
* - Session boundaries
|
|
15
|
-
* `
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* - `
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* -
|
|
22
|
-
*
|
|
23
|
-
*
|
|
14
|
+
* - Session boundaries come from the firmware's own envelope fields:
|
|
15
|
+
* `ts_start = parse(start)`, `ts_end = parse(end)`. `total_minutes` is
|
|
16
|
+
* their difference. Deriving the envelope from block instants would
|
|
17
|
+
* under-report any session whose first/last minutes went unclassified.
|
|
18
|
+
* - `session_id` = `nanoid(24) + '_' + fnv1a32hex(device_id | user_id |
|
|
19
|
+
* ts_session_start)` (principle 25, locked) — collision-safe even with
|
|
20
|
+
* corrupted timestamps.
|
|
21
|
+
* - `night_of` = 6pm-6pm rule applied to `ts_start` (see `time.ts`).
|
|
22
|
+
* - Stages: one row per classified block, carrying `session_id` and the
|
|
23
|
+
* DDL's integer `stage` code. `primary` is the session envelope marker,
|
|
24
|
+
* not a stage, so it produces no `sleep_stage` row — the DDL's stage
|
|
25
|
+
* enum (1=awake, 2=light, 3=deep, 5=rem) has no code for it. Unknown
|
|
26
|
+
* block types are likewise skipped; nothing is lost, because...
|
|
27
|
+
* - Raw: every input row is preserved in `sleep_raw` regardless of the
|
|
28
|
+
* primary/confidence filter, flattened onto the DDL's columns, so
|
|
29
|
+
* downstream reprocessing can revisit sessions with new heuristics.
|
|
30
|
+
*
|
|
31
|
+
* Principle 20 boundary: firmware `block_type` strings are translated to our
|
|
32
|
+
* integer codes here and never reach the warehouse.
|
|
24
33
|
*/
|
|
34
|
+
import { nanoid } from 'nanoid';
|
|
25
35
|
import { computeNightOf, parseTimestamp } from './time';
|
|
26
36
|
const MINUTE_MS = 60000;
|
|
27
37
|
const PRIMARY = 'primary';
|
|
28
38
|
const CONFIDENCE_FLOOR = 0.7;
|
|
39
|
+
/**
|
|
40
|
+
* Block width in minutes when the firmware revision omits `unit_length`.
|
|
41
|
+
* Firmware doc §Sleep processing: blocks are 1-min wide by convention.
|
|
42
|
+
*/
|
|
43
|
+
export const DEFAULT_BLOCK_MINUTES = 1;
|
|
44
|
+
/**
|
|
45
|
+
* Firmware `block_type` → `sleep_stage.stage` code (spec §Table schema:
|
|
46
|
+
* `stage SMALLINT NOT NULL -- 1=awake, 2=light, 3=deep, 5=rem`).
|
|
47
|
+
*
|
|
48
|
+
* `primary` is deliberately absent: it marks the session envelope, not a
|
|
49
|
+
* sleep stage. The enum is intentionally sparse (no 4) to match the DDL
|
|
50
|
+
* comment verbatim.
|
|
51
|
+
*/
|
|
52
|
+
export const SLEEP_STAGE_CODES = Object.freeze({
|
|
53
|
+
awake: 1,
|
|
54
|
+
light: 2,
|
|
55
|
+
deep: 3,
|
|
56
|
+
rem: 5,
|
|
57
|
+
});
|
|
58
|
+
/** Reverse lookup for the stage-minute accumulator + diagnostics. */
|
|
59
|
+
export const SLEEP_STAGE_NAMES = Object.freeze({
|
|
60
|
+
1: 'awake',
|
|
61
|
+
2: 'light',
|
|
62
|
+
3: 'deep',
|
|
63
|
+
5: 'rem',
|
|
64
|
+
});
|
|
65
|
+
/** Per-block width, honouring a firmware-supplied `unit_length`. */
|
|
66
|
+
function blockMinutes(row) {
|
|
67
|
+
return typeof row.unit_length === 'number' && row.unit_length > 0
|
|
68
|
+
? row.unit_length
|
|
69
|
+
: DEFAULT_BLOCK_MINUTES;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* `sleep_raw.quality` is NOT NULL. Firmware revisions that carry a native
|
|
73
|
+
* `quality` pass it through verbatim; older revisions derive it from the
|
|
74
|
+
* block confidence (0..1 → 0..100) so the column is always populated.
|
|
75
|
+
*/
|
|
76
|
+
function rawQuality(row) {
|
|
77
|
+
return typeof row.quality === 'number'
|
|
78
|
+
? row.quality
|
|
79
|
+
: Math.round(row.confidence * 100);
|
|
80
|
+
}
|
|
29
81
|
export function reconstructSleepSessions(rows, ctx) {
|
|
30
82
|
const sleep_session = [];
|
|
31
83
|
const sleep_stage = [];
|
|
32
84
|
const sleep_raw = [];
|
|
33
|
-
// Raw pass —
|
|
85
|
+
// Raw pass — every input row preserved for reprocessing, including rows
|
|
86
|
+
// from sessions the primary/confidence filter drops.
|
|
34
87
|
for (const row of rows) {
|
|
35
88
|
sleep_raw.push({
|
|
36
89
|
ts: parseTimestamp(row.timestamp),
|
|
90
|
+
ts_session_start: parseTimestamp(row.start),
|
|
37
91
|
brand: ctx.brand,
|
|
38
92
|
family_id: ctx.familyId,
|
|
39
93
|
user_id: ctx.userId,
|
|
40
94
|
device_id: ctx.deviceId,
|
|
41
|
-
|
|
95
|
+
quality: rawQuality(row),
|
|
96
|
+
unit_length: typeof row.unit_length === 'number' ? row.unit_length : null,
|
|
42
97
|
});
|
|
43
98
|
}
|
|
44
99
|
// Group by `start`.
|
|
@@ -56,48 +111,90 @@ export function reconstructSleepSessions(rows, ctx) {
|
|
|
56
111
|
const hasQualifyingPrimary = blocks.some(b => b.block_type === PRIMARY && b.confidence >= CONFIDENCE_FLOOR);
|
|
57
112
|
if (!hasQualifyingPrimary)
|
|
58
113
|
continue;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
const nightOf = computeNightOf(
|
|
65
|
-
const sessionId = makeSessionId(ctx
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
114
|
+
// Envelope from the firmware's own session fields. `end` is exclusive of
|
|
115
|
+
// nothing — it is the session end instant, so total is a plain delta.
|
|
116
|
+
const tsStart = parseTimestamp(startKey);
|
|
117
|
+
const tsEnd = parseTimestamp(blocks[0].end);
|
|
118
|
+
const totalMinutes = Math.max(0, Math.round((tsEnd.getTime() - tsStart.getTime()) / MINUTE_MS));
|
|
119
|
+
const nightOf = computeNightOf(tsStart, ctx.userTimezone);
|
|
120
|
+
const sessionId = makeSessionId(ctx, tsStart);
|
|
121
|
+
// Stage rows + per-stage minute accumulation in one pass.
|
|
122
|
+
const stageMinutes = {
|
|
123
|
+
awake: 0,
|
|
124
|
+
light: 0,
|
|
125
|
+
deep: 0,
|
|
126
|
+
rem: 0,
|
|
127
|
+
};
|
|
128
|
+
let confidenceSum = 0;
|
|
129
|
+
for (const b of blocks) {
|
|
130
|
+
confidenceSum += b.confidence;
|
|
131
|
+
const code = SLEEP_STAGE_CODES[b.block_type];
|
|
132
|
+
if (code === undefined) {
|
|
133
|
+
// `primary` (envelope marker) and any unrecognised firmware block
|
|
134
|
+
// type. Not a stage — preserved in sleep_raw, skipped here.
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
stageMinutes[SLEEP_STAGE_NAMES[code]] += blockMinutes(b);
|
|
79
138
|
sleep_stage.push({
|
|
80
|
-
ts:
|
|
139
|
+
ts: parseTimestamp(b.timestamp),
|
|
81
140
|
brand: ctx.brand,
|
|
82
141
|
family_id: ctx.familyId,
|
|
83
142
|
user_id: ctx.userId,
|
|
84
143
|
device_id: ctx.deviceId,
|
|
85
144
|
session_id: sessionId,
|
|
86
|
-
stage:
|
|
145
|
+
stage: code,
|
|
87
146
|
confidence: b.confidence,
|
|
88
147
|
});
|
|
89
148
|
}
|
|
90
|
-
|
|
91
|
-
|
|
149
|
+
sleep_session.push({
|
|
150
|
+
brand: ctx.brand,
|
|
151
|
+
family_id: ctx.familyId,
|
|
152
|
+
user_id: ctx.userId,
|
|
153
|
+
device_id: ctx.deviceId,
|
|
154
|
+
session_id: sessionId,
|
|
155
|
+
ts_start: tsStart,
|
|
156
|
+
ts_end: tsEnd,
|
|
157
|
+
total_minutes: totalMinutes,
|
|
158
|
+
deep_minutes: stageMinutes.deep,
|
|
159
|
+
rem_minutes: stageMinutes.rem,
|
|
160
|
+
light_minutes: stageMinutes.light,
|
|
161
|
+
awake_minutes: stageMinutes.awake,
|
|
162
|
+
avg_confidence: blocks.length > 0 ? confidenceSum / blocks.length : null,
|
|
163
|
+
night_of: nightOf,
|
|
164
|
+
});
|
|
92
165
|
}
|
|
93
166
|
return { sleep_session, sleep_stage, sleep_raw };
|
|
94
167
|
}
|
|
95
168
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
169
|
+
* Session id components (principle 25, locked):
|
|
170
|
+
* `nanoid(24) + '_' + fnv1a32hex(device_id | user_id | ts_session_start)`
|
|
171
|
+
*
|
|
172
|
+
* The random prefix makes ids collision-safe even when the firmware emits
|
|
173
|
+
* corrupted/duplicated timestamps; the hash suffix is deterministic over the
|
|
174
|
+
* identifying tuple so ids remain diagnosable (same device+user+start ⇒
|
|
175
|
+
* same suffix). The random source is injectable via `ctx.idGenerator` to
|
|
176
|
+
* keep the mapper testable — the suffix is always deterministic.
|
|
177
|
+
*/
|
|
178
|
+
export function sessionIdComponents(ctx, tsSessionStart) {
|
|
179
|
+
const random = ctx.idGenerator ? ctx.idGenerator() : nanoid(24);
|
|
180
|
+
const hash = fnv1a32hex(`${ctx.deviceId}|${ctx.userId}|${tsSessionStart.toISOString()}`);
|
|
181
|
+
return { random, hash };
|
|
182
|
+
}
|
|
183
|
+
function makeSessionId(ctx, startTs) {
|
|
184
|
+
const { random, hash } = sessionIdComponents(ctx, startTs);
|
|
185
|
+
return `${random}_${hash}`;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* FNV-1a 32-bit, hex-encoded (8 lowercase hex chars). Implemented inline —
|
|
189
|
+
* a dependency for 10 lines of arithmetic is not worth the supply-chain
|
|
190
|
+
* surface, and the mapper only needs a stable non-cryptographic digest.
|
|
99
191
|
*/
|
|
100
|
-
function
|
|
101
|
-
|
|
192
|
+
export function fnv1a32hex(input) {
|
|
193
|
+
let h = 0x811C9DC5;
|
|
194
|
+
for (let i = 0; i < input.length; i++) {
|
|
195
|
+
h ^= input.charCodeAt(i);
|
|
196
|
+
h = Math.imul(h, 0x01000193) >>> 0;
|
|
197
|
+
}
|
|
198
|
+
return h.toString(16).padStart(8, '0');
|
|
102
199
|
}
|
|
103
200
|
//# sourceMappingURL=sleep.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../../src/sync/mapper/sleep.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../../src/sync/mapper/sleep.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,13 @@ export interface MapperContext {
|
|
|
18
18
|
deviceId: string;
|
|
19
19
|
/** IANA timezone string, e.g. 'America/Los_Angeles'. */
|
|
20
20
|
userTimezone: string;
|
|
21
|
+
/**
|
|
22
|
+
* Random-id source for session ids (principle 25). Defaults to
|
|
23
|
+
* `() => nanoid(24)`. Injectable so tests can keep the mapper
|
|
24
|
+
* deterministic — the hash suffix of a session id is always
|
|
25
|
+
* deterministic regardless of this generator.
|
|
26
|
+
*/
|
|
27
|
+
idGenerator?: () => string;
|
|
21
28
|
}
|
|
22
29
|
export interface FirmwareHRVRow {
|
|
23
30
|
timestamp: string;
|
|
@@ -54,6 +61,18 @@ export interface FirmwareSleepRow {
|
|
|
54
61
|
block_type: string;
|
|
55
62
|
confidence: number;
|
|
56
63
|
timestamp: string;
|
|
64
|
+
/**
|
|
65
|
+
* Raw per-block quality score, when the firmware revision carries one.
|
|
66
|
+
* Passed through verbatim to `sleep_raw.quality`. Revisions that omit it
|
|
67
|
+
* fall back to `round(confidence * 100)` — see `mapper/sleep.ts`.
|
|
68
|
+
*/
|
|
69
|
+
quality?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Block width in minutes, when the firmware revision carries one.
|
|
72
|
+
* Passed through verbatim to `sleep_raw.unit_length`; drives stage-minute
|
|
73
|
+
* accumulation. Defaults to `DEFAULT_BLOCK_MINUTES` (1) when absent.
|
|
74
|
+
*/
|
|
75
|
+
unit_length?: number;
|
|
57
76
|
}
|
|
58
77
|
export interface FirmwareBatteryRow {
|
|
59
78
|
timestamp: string;
|
|
@@ -78,13 +97,21 @@ export interface FirmwareExport {
|
|
|
78
97
|
battery_table: FirmwareBatteryRow[];
|
|
79
98
|
ring: FirmwareRingConfig;
|
|
80
99
|
}
|
|
81
|
-
|
|
82
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Tenant columns every warehouse row carries (spec §Table schema —
|
|
102
|
+
* "every sensor row carries brand, family_id, user_id"). Split out from
|
|
103
|
+
* `BaseRow` because `sleep_session` has no `ts` column: its time axis is
|
|
104
|
+
* `ts_start` / `ts_end`.
|
|
105
|
+
*/
|
|
106
|
+
interface TenantRow {
|
|
83
107
|
brand: string;
|
|
84
108
|
family_id: string;
|
|
85
109
|
user_id: string;
|
|
86
110
|
device_id: string;
|
|
87
111
|
}
|
|
112
|
+
interface BaseRow extends TenantRow {
|
|
113
|
+
ts: Date;
|
|
114
|
+
}
|
|
88
115
|
export interface HrvRow extends BaseRow {
|
|
89
116
|
hrv_ms: number | null;
|
|
90
117
|
stress: number | null;
|
|
@@ -104,24 +131,53 @@ export interface TemperatureRow extends BaseRow {
|
|
|
104
131
|
export interface ActivityRow extends BaseRow {
|
|
105
132
|
steps: number;
|
|
106
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* `activity_bucket` warehouse row — 10-min calories/distance. Steps are NOT
|
|
136
|
+
* carried here: they live in `activity` at 1-min resolution after unnest
|
|
137
|
+
* (spec §Table schema). A `steps` field here would silently double-count.
|
|
138
|
+
*/
|
|
107
139
|
export interface ActivityBucketRow extends BaseRow {
|
|
108
|
-
steps: number;
|
|
109
140
|
calories: number;
|
|
110
141
|
distance_km: number;
|
|
111
142
|
}
|
|
112
|
-
|
|
143
|
+
/**
|
|
144
|
+
* `sleep_session` warehouse row. Column names + nullability mirror the DDL
|
|
145
|
+
* in `core/schemas.ts` exactly, so `row[c]` keyed by
|
|
146
|
+
* `columnOrder.sleep_session` yields correct positional appender input.
|
|
147
|
+
*
|
|
148
|
+
* No `ts` — the DDL partitions on `day(ts_start)`.
|
|
149
|
+
*/
|
|
150
|
+
export interface SleepSessionRow extends TenantRow {
|
|
113
151
|
session_id: string;
|
|
114
|
-
|
|
115
|
-
|
|
152
|
+
ts_start: Date;
|
|
153
|
+
ts_end: Date;
|
|
154
|
+
total_minutes: number;
|
|
155
|
+
deep_minutes: number | null;
|
|
156
|
+
rem_minutes: number | null;
|
|
157
|
+
light_minutes: number | null;
|
|
158
|
+
awake_minutes: number | null;
|
|
159
|
+
avg_confidence: number | null;
|
|
116
160
|
night_of: Date;
|
|
117
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* `sleep_stage` warehouse row. `stage` is the DDL's integer code
|
|
164
|
+
* (`SLEEP_STAGE_CODES`), never the raw firmware `block_type` string —
|
|
165
|
+
* principle 20: firmware enums do not reach our schema.
|
|
166
|
+
*/
|
|
118
167
|
export interface SleepStageRow extends BaseRow {
|
|
119
168
|
session_id: string;
|
|
120
|
-
stage:
|
|
121
|
-
confidence: number;
|
|
169
|
+
stage: number;
|
|
170
|
+
confidence: number | null;
|
|
122
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* `sleep_raw` warehouse row (`collected_only`). Preserves each firmware
|
|
174
|
+
* block for reprocessing, flattened onto the DDL's columns rather than
|
|
175
|
+
* stashed as an opaque payload blob.
|
|
176
|
+
*/
|
|
123
177
|
export interface SleepRawRow extends BaseRow {
|
|
124
|
-
|
|
178
|
+
ts_session_start: Date;
|
|
179
|
+
quality: number;
|
|
180
|
+
unit_length: number | null;
|
|
125
181
|
}
|
|
126
182
|
export interface DeviceEventRow extends BaseRow {
|
|
127
183
|
event_type: string;
|
|
@@ -144,7 +200,7 @@ export interface DeviceBatteryRow extends BaseRow {
|
|
|
144
200
|
* (`data_type`, `start_time`, `end_time`, `weeks`) are produced by a
|
|
145
201
|
* consumer-provided `RingConfigTranslator` (see below).
|
|
146
202
|
*/
|
|
147
|
-
export interface DeviceConfigRow extends
|
|
203
|
+
export interface DeviceConfigRow extends TenantRow {
|
|
148
204
|
data_type: number;
|
|
149
205
|
interval_minutes: number;
|
|
150
206
|
start_time: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sync/mapper/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sync/mapper/types.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/scheduler.d.ts
CHANGED
|
@@ -43,6 +43,13 @@ export interface SyncCoordinator {
|
|
|
43
43
|
fetchIncremental: (ctx: AttachContext) => Promise<Array<{
|
|
44
44
|
ok: boolean;
|
|
45
45
|
}>>;
|
|
46
|
+
/**
|
|
47
|
+
* Day-first baseline recompute (Sprint 5 T-15). Runs AFTER fetch so the
|
|
48
|
+
* quantiles see rows that just arrived from R2, not just locally-flushed
|
|
49
|
+
* ones — a baseline computed before the fetch would be short a day on
|
|
50
|
+
* every multi-device family. Optional; failures never fail the cycle.
|
|
51
|
+
*/
|
|
52
|
+
computeBaselines?: () => Promise<void>;
|
|
46
53
|
onCycleComplete?: () => Promise<void>;
|
|
47
54
|
}
|
|
48
55
|
/** Debug/info logger — matches `@mongrov/core` shape narrowly. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/sync/scheduler.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/sync/scheduler.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/scheduler.js
CHANGED
|
@@ -98,6 +98,20 @@ _SyncScheduler_config = new WeakMap(), _SyncScheduler_state = new WeakMap(), _Sy
|
|
|
98
98
|
await __classPrivateFieldGet(this, _SyncScheduler_config, "f").coordinator.pushAll(__classPrivateFieldGet(this, _SyncScheduler_config, "f").tables, __classPrivateFieldGet(this, _SyncScheduler_config, "f").ctx);
|
|
99
99
|
await __classPrivateFieldGet(this, _SyncScheduler_config, "f").coordinator.pushClosesForDeviceConfig?.(__classPrivateFieldGet(this, _SyncScheduler_config, "f").ctx);
|
|
100
100
|
await __classPrivateFieldGet(this, _SyncScheduler_config, "f").coordinator.fetchIncremental(__classPrivateFieldGet(this, _SyncScheduler_config, "f").ctx);
|
|
101
|
+
// Baselines are derived data — a failure here leaves the previous
|
|
102
|
+
// (still-valid) rows in place and must not mark the cycle failed,
|
|
103
|
+
// which would otherwise strand the scheduler in `error` and stop
|
|
104
|
+
// future flushes over a stale percentile.
|
|
105
|
+
if (__classPrivateFieldGet(this, _SyncScheduler_config, "f").coordinator.computeBaselines) {
|
|
106
|
+
try {
|
|
107
|
+
await __classPrivateFieldGet(this, _SyncScheduler_config, "f").coordinator.computeBaselines();
|
|
108
|
+
}
|
|
109
|
+
catch (cause) {
|
|
110
|
+
__classPrivateFieldGet(this, _SyncScheduler_config, "f").logger.warn('scheduler.cycle.baselines_failed', {
|
|
111
|
+
error: String(cause),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
101
115
|
await __classPrivateFieldGet(this, _SyncScheduler_config, "f").coordinator.onCycleComplete?.();
|
|
102
116
|
__classPrivateFieldGet(this, _SyncScheduler_config, "f").logger.debug('scheduler.cycle.ok');
|
|
103
117
|
__classPrivateFieldGet(this, _SyncScheduler_instances, "m", _SyncScheduler_setState).call(this, 'idle');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/sync/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;;;;;;;;;;;;;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/sync/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,8 @@ export interface FakeEngine extends AnalyticsEngine {
|
|
|
20
20
|
}[];
|
|
21
21
|
queueRows: (sqlSubstring: string, rows: unknown[]) => void;
|
|
22
22
|
setError: (err: Error | null) => void;
|
|
23
|
+
/** Seed the roster returned by `getFamilyMembers()`. */
|
|
24
|
+
setFamilyMembers: (ids: string[]) => void;
|
|
23
25
|
}
|
|
24
26
|
export declare function createFakeEngine(): FakeEngine;
|
|
25
27
|
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/tools/__fakes__/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAEvD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,UAAW,SAAQ,eAAe;IACjD,QAAQ,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EAAE,CAAA;IAClE,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IAC1D,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/tools/__fakes__/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAEvD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,UAAW,SAAQ,eAAe;IACjD,QAAQ,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EAAE,CAAA;IAClE,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IAC1D,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAA;IACrC,wDAAwD;IACxD,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CAC1C;AAED,wBAAgB,gBAAgB,IAAI,UAAU,CA4C7C"}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
export function createFakeEngine() {
|
|
2
2
|
const queues = [];
|
|
3
|
+
let familyMembers = [];
|
|
3
4
|
const calls = [];
|
|
4
5
|
let error = null;
|
|
5
6
|
const engine = {
|
|
6
7
|
async attach() { },
|
|
7
8
|
async detach() { },
|
|
9
|
+
async dismissInsight() { },
|
|
10
|
+
async getFamilyMembers() {
|
|
11
|
+
// Honour `setError` so fail-closed tests exercise a real throw from
|
|
12
|
+
// the membership path, not an incidental empty roster.
|
|
13
|
+
if (error)
|
|
14
|
+
throw error;
|
|
15
|
+
return familyMembers;
|
|
16
|
+
},
|
|
8
17
|
async execute(sql, params) {
|
|
9
18
|
calls.push({ sql, params: params ?? {} });
|
|
10
19
|
if (error)
|
|
@@ -32,6 +41,7 @@ export function createFakeEngine() {
|
|
|
32
41
|
calls,
|
|
33
42
|
queueRows(substring, rows) { queues.push({ substring, rows }); },
|
|
34
43
|
setError(err) { error = err; },
|
|
44
|
+
setFamilyMembers(ids) { familyMembers = ids; },
|
|
35
45
|
};
|
|
36
46
|
return engine;
|
|
37
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/tools/__fakes__/engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/tools/__fakes__/engine.ts"],"names":[],"mappings":"AAwBA,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAA6C,EAAE,CAAA;IAC3D,IAAI,aAAa,GAAa,EAAE,CAAA;IAChC,MAAM,KAAK,GAAuD,EAAE,CAAA;IACpE,IAAI,KAAK,GAAiB,IAAI,CAAA;IAE9B,MAAM,MAAM,GAAe;QACzB,KAAK,CAAC,MAAM,KAAI,CAAC;QACjB,KAAK,CAAC,MAAM,KAAI,CAAC;QACjB,KAAK,CAAC,cAAc,KAAI,CAAC;QACzB,KAAK,CAAC,gBAAgB;YACpB,oEAAoE;YACpE,uDAAuD;YACvD,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAA;YACtB,OAAO,aAAa,CAAA;QACtB,CAAC;QACD,KAAK,CAAC,OAAO,CAAI,GAAW,EAAE,MAAgC;YAC5D,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC,CAAA;YACzC,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAA;YACtB,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;YAC5D,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,OAAO,EAAS,CAAA;YAChC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YACjC,OAAO,CAAC,CAAC,IAAW,CAAA;QACtB,CAAC;QACD,MAAM;YACJ,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;QACnD,CAAC;QACD,cAAc;YACZ,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAA;QAC3D,CAAC;QACD,KAAK,EAAE,UAAU;QACjB,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,IAAI;QACV,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC;QACzB,KAAK,CAAC,YAAY,KAAI,CAAC;QACvB,KAAK,CAAC,aAAa,KAAK,OAAO,IAAI,CAAA,CAAC,CAAC;QACrC,KAAK,CAAC,KAAK,KAAI,CAAC;QAChB,KAAK;QACL,SAAS,CAAC,SAAS,EAAE,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA,CAAC,CAAC;QAC/D,QAAQ,CAAC,GAAG,IAAI,KAAK,GAAG,GAAG,CAAA,CAAC,CAAC;QAC7B,gBAAgB,CAAC,GAAG,IAAI,aAAa,GAAG,GAAG,CAAA,CAAC,CAAC;KAC9C,CAAA;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -3,10 +3,20 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `familyScopeAuthorize` — grants access iff `args.userId` is either
|
|
5
5
|
* the requester themselves or another member of the requester's
|
|
6
|
-
* family.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* family.
|
|
7
|
+
*
|
|
8
|
+
* Membership always resolves through the engine's configured
|
|
9
|
+
* `FamilyMembersProvider` (principle 39 — "Rules engine and AI tools
|
|
10
|
+
* share the same source of truth"): an explicitly-passed
|
|
11
|
+
* `config.familyMembersProvider` wins, otherwise `analytics
|
|
12
|
+
* .getFamilyMembers()` delegates to the one wired at `createAnalytics`.
|
|
13
|
+
*
|
|
14
|
+
* There is deliberately no SQL fallback. The spec's illustrative
|
|
15
|
+
* `SELECT 1 FROM family_member ...` referenced a table that no DDL in
|
|
16
|
+
* this package ever creates, so that path could only ever throw and
|
|
17
|
+
* fail closed — silently denying every cross-member query on any
|
|
18
|
+
* install that didn't pass a provider. Membership lives in the RxDB
|
|
19
|
+
* Family doc, not in DuckDB.
|
|
10
20
|
*
|
|
11
21
|
* Both hooks fail closed on any error — provider throws, engine
|
|
12
22
|
* throws, missing/malformed args — return `false` rather than
|
|
@@ -23,14 +33,11 @@ export interface AuthorizeConfig {
|
|
|
23
33
|
}
|
|
24
34
|
export declare function familyScopeAuthorize(analytics: AnalyticsEngine, config?: AuthorizeConfig): AuthorizeFn;
|
|
25
35
|
/**
|
|
26
|
-
* `orgScopeAuthorize` — parity with family scope
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* When `familyMembersProvider` is supplied, the same provider is
|
|
32
|
-
* consulted (v0.1.0 shim — a dedicated `orgMembersProvider` will
|
|
33
|
-
* split out once orgs land).
|
|
36
|
+
* `orgScopeAuthorize` — parity with family scope. Orgs are not
|
|
37
|
+
* first-class in v0.1.0; the ctx `familyId` is treated as the org id
|
|
38
|
+
* until org membership is wired through `RequestContext`, and the same
|
|
39
|
+
* membership provider is consulted (v0.1.0 shim — a dedicated
|
|
40
|
+
* `orgMembersProvider` splits out once orgs land).
|
|
34
41
|
*/
|
|
35
42
|
export declare function orgScopeAuthorize(analytics: AnalyticsEngine, config?: AuthorizeConfig): AuthorizeFn;
|
|
36
43
|
//# sourceMappingURL=authorize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/tools/authorize.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/tools/authorize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;CAC9C;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,eAAe,EAC1B,MAAM,GAAE,eAAoB,GAC3B,WAAW,CAuBb;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,eAAe,EAC1B,MAAM,GAAE,eAAoB,GAC3B,WAAW,CAuBb"}
|