@justair/justair-library 7.6.0-alpha.f80fd11 → 7.6.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.
|
@@ -11,9 +11,7 @@ export const VISIBLE_SITE_MONITOR_FILTER: Readonly<{
|
|
|
11
11
|
isPrivate: Readonly<{
|
|
12
12
|
$ne: true;
|
|
13
13
|
}>;
|
|
14
|
-
isActive:
|
|
15
|
-
$ne: false;
|
|
16
|
-
}>;
|
|
14
|
+
isActive: true;
|
|
17
15
|
}>;
|
|
18
16
|
export function projectSubscribedMonitors(subscribedDevices?: Array<{
|
|
19
17
|
deviceId: import("mongoose").Types.ObjectId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribedDevices.d.ts","sourceRoot":"","sources":["../../src/utils/subscribedDevices.js"],"names":[],"mappings":"AA0FA;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"subscribedDevices.d.ts","sourceRoot":"","sources":["../../src/utils/subscribedDevices.js"],"names":[],"mappings":"AA0FA;;;;;;;;GASG;AA+CH;;;;;GAGG;AA6LI,8DANI,KAAK,CAAC;IAAE,QAAQ,EAAE,OAAO,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC;IAC1D,UAAU,EAAE,OAAO,6BAA6B,EAAE,UAAU,CAAA;CAAE,CAAC,8BACzD;IAAE,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,KAC7E,OAAO,CAAC,KAAK,CAAC,OAAO,UAAU,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAA;CAAE,GAC9D,OAAO,CAAC,OAAO,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CA0BxD;AA0EM,0DAPI,KAAK,CAAC;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC;QAClD,QAAQ,EAAE,OAAO,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC;QAC5C,UAAU,EAAE,OAAO,6BAA6B,EAAE,UAAU,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,mCAC5D;IAAE,0BAA0B,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,KAClF,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;CAAE,GACnD,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAmErE"}
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -293,16 +293,16 @@ export {
|
|
|
293
293
|
// being retired rather than kept in step with it. Nothing should store this
|
|
294
294
|
// result — see the module header for the five bugs a stored copy caused.
|
|
295
295
|
//
|
|
296
|
+
// Both resolvers are only correct for users whose subscribedDevices has been
|
|
297
|
+
// backfilled from subscribedMonitors — read the PRECONDITION block in the
|
|
298
|
+
// module header before pointing a service at either of them.
|
|
299
|
+
//
|
|
296
300
|
// resolveSubscribedMonitorIdsByUser — the batch form. One Sites lookup for
|
|
297
301
|
// a whole cohort. What alert runs, org pages and
|
|
298
302
|
// session responses should call.
|
|
299
303
|
// projectSubscribedMonitors — the single-user rule the batch form is built
|
|
300
304
|
// on. Named after the field being retired; it
|
|
301
305
|
// gets renamed when that field is dropped.
|
|
302
|
-
//
|
|
303
|
-
// Only correct for users whose subscribedDevices has been backfilled from
|
|
304
|
-
// subscribedMonitors — see the PRECONDITION block in the module header
|
|
305
|
-
// before pointing a service at these.
|
|
306
306
|
// VISIBLE_SITE_MONITOR_FILTER — the privacy predicate every consumer must
|
|
307
307
|
// apply when turning a Site into monitor ids.
|
|
308
308
|
// Sites.monitorIds is unfiltered; reading it
|
|
@@ -116,15 +116,20 @@ export const SUBSCRIBED_DEVICES_ERRORS = Object.freeze({
|
|
|
116
116
|
// "_id",
|
|
117
117
|
// ).lean();
|
|
118
118
|
//
|
|
119
|
-
// `isActive:
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
// `
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
//
|
|
119
|
+
// `isActive: true` is an EXACT match, and that asymmetry with the `$ne` above
|
|
120
|
+
// is DELIBERATE — do not "fix" it to `{ $ne: false }`. The two clauses answer
|
|
121
|
+
// different questions. `isPrivate` is a privacy gate: a monitor with no
|
|
122
|
+
// `isPrivate` key was never marked private, so excluding it would hide a
|
|
123
|
+
// monitor its followers are entitled to see. `isActive` is an eligibility
|
|
124
|
+
// gate: a monitor only earns a place in an alert audience by positively
|
|
125
|
+
// asserting it is active. A document with no `isActive` key has made no such
|
|
126
|
+
// assertion, and the safe reading of "we don't know" is to leave it out rather
|
|
127
|
+
// than alert on it.
|
|
128
|
+
//
|
|
129
|
+
// So the failure modes are not symmetric and should not be made symmetric.
|
|
130
|
+
// Over-including here means alerting people about a monitor nobody confirmed
|
|
131
|
+
// is live; under-including means one unconfirmed monitor is missing from an
|
|
132
|
+
// audience until someone sets the flag. This predicate takes the second.
|
|
128
133
|
//
|
|
129
134
|
// `monitorState: "Deployed"` is deliberately NOT here. That is an
|
|
130
135
|
// alerting-eligibility rule, not a visibility rule, and it belongs to the
|
|
@@ -137,10 +142,11 @@ export const SUBSCRIBED_DEVICES_ERRORS = Object.freeze({
|
|
|
137
142
|
// top-level-only freeze still lets a consumer write
|
|
138
143
|
// `VISIBLE_SITE_MONITOR_FILTER.isPrivate.$ne = false` — and because every
|
|
139
144
|
// consumer spreads THIS instance, that one write flips the privacy predicate
|
|
140
|
-
// for the whole process.
|
|
145
|
+
// for the whole process. `isPrivate` is the only nested object here; freeze it
|
|
146
|
+
// too, and freeze any operator object a future clause introduces.
|
|
141
147
|
export const VISIBLE_SITE_MONITOR_FILTER = Object.freeze({
|
|
142
148
|
isPrivate: Object.freeze({ $ne: true }),
|
|
143
|
-
isActive:
|
|
149
|
+
isActive: true,
|
|
144
150
|
});
|
|
145
151
|
|
|
146
152
|
// Dedupe by string form, keep the caller's ObjectId instances. Two equal
|
|
@@ -398,10 +404,13 @@ export const projectSubscribedMonitors = async (
|
|
|
398
404
|
// to nothing, so their alerts stop) is the subscription-identity question
|
|
399
405
|
// tracked in TODOS, and is deliberately not papered over here.
|
|
400
406
|
//
|
|
401
|
-
// Users are keyed by `String(user._id)`, so callers look up with the same.
|
|
402
|
-
//
|
|
403
|
-
//
|
|
404
|
-
//
|
|
407
|
+
// Users are keyed by `String(user._id)`, so callers look up with the same.
|
|
408
|
+
// Anything in the cohort that is not a user object carrying an `_id` — a
|
|
409
|
+
// missing `_id`, a `null` slot, a bare id string — throws COHORT_USER_MISSING_ID
|
|
410
|
+
// rather than being skipped. Skipping would silently remove a real person from
|
|
411
|
+
// an alert audience, which is the failure mode this whole module exists to
|
|
412
|
+
// avoid, and a caller cannot tell a dropped entry apart from one that resolved
|
|
413
|
+
// to nothing.
|
|
405
414
|
//
|
|
406
415
|
// Consumers can shrink the cohort by pushing the AQI-capability predicate into
|
|
407
416
|
// the Users query, so rows that can never alert are not loaded at all.
|
|
@@ -665,15 +665,17 @@ describe('resolveSubscribedMonitorIdsByUser — rejects what would otherwise fai
|
|
|
665
665
|
});
|
|
666
666
|
|
|
667
667
|
describe('VISIBLE_SITE_MONITOR_FILTER', () => {
|
|
668
|
-
test('
|
|
669
|
-
//
|
|
670
|
-
//
|
|
671
|
-
//
|
|
672
|
-
//
|
|
673
|
-
//
|
|
668
|
+
test('privacy uses $ne, eligibility uses an exact match — deliberately', () => {
|
|
669
|
+
// The asymmetry is the point, and this test exists to stop it being
|
|
670
|
+
// "fixed". isPrivate is a privacy gate: $ne keeps a monitor that was never
|
|
671
|
+
// marked private, which its followers are entitled to see. isActive is an
|
|
672
|
+
// eligibility gate: a monitor earns a place in an alert audience only by
|
|
673
|
+
// positively asserting it is active, so a document that has made no such
|
|
674
|
+
// assertion stays out. Confirmed product decision — flipping either half
|
|
675
|
+
// is a behaviour change, not a cleanup.
|
|
674
676
|
expect(VISIBLE_SITE_MONITOR_FILTER).toEqual({
|
|
675
677
|
isPrivate: { $ne: true },
|
|
676
|
-
isActive:
|
|
678
|
+
isActive: true,
|
|
677
679
|
});
|
|
678
680
|
});
|
|
679
681
|
|
|
@@ -683,12 +685,12 @@ describe('VISIBLE_SITE_MONITOR_FILTER', () => {
|
|
|
683
685
|
// predicate for every consumer that spreads this instance.
|
|
684
686
|
expect(Object.isFrozen(VISIBLE_SITE_MONITOR_FILTER)).toBe(true);
|
|
685
687
|
expect(Object.isFrozen(VISIBLE_SITE_MONITOR_FILTER.isPrivate)).toBe(true);
|
|
686
|
-
expect(Object.isFrozen(VISIBLE_SITE_MONITOR_FILTER.isActive)).toBe(true);
|
|
687
688
|
});
|
|
688
689
|
|
|
689
690
|
test('a nested write is rejected rather than shared with every consumer', () => {
|
|
691
|
+
// ES modules are strict, so a write to a frozen property throws rather
|
|
692
|
+
// than failing silently.
|
|
690
693
|
expect(() => {
|
|
691
|
-
'use strict';
|
|
692
694
|
VISIBLE_SITE_MONITOR_FILTER.isPrivate.$ne = false;
|
|
693
695
|
}).toThrow(TypeError);
|
|
694
696
|
|