camstack 1.2.178 → 1.2.179
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.
|
@@ -24024,9 +24024,9 @@ var require_zod = __commonJS({
|
|
|
24024
24024
|
}
|
|
24025
24025
|
});
|
|
24026
24026
|
|
|
24027
|
-
// ../system/dist/dist-
|
|
24028
|
-
var
|
|
24029
|
-
"../system/dist/dist-
|
|
24027
|
+
// ../system/dist/dist-DePB7uwU.js
|
|
24028
|
+
var require_dist_DePB7uwU = __commonJS({
|
|
24029
|
+
"../system/dist/dist-DePB7uwU.js"(exports) {
|
|
24030
24030
|
"use strict";
|
|
24031
24031
|
var zod = require_zod();
|
|
24032
24032
|
__require("crypto");
|
|
@@ -39852,6 +39852,7 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
39852
39852
|
"detection-blind",
|
|
39853
39853
|
"nodes",
|
|
39854
39854
|
"addons",
|
|
39855
|
+
"addon-updates",
|
|
39855
39856
|
"updates"
|
|
39856
39857
|
]);
|
|
39857
39858
|
var NcStateSummaryPreviewSectionSchema = zod.z.object({
|
|
@@ -40238,7 +40239,19 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
40238
40239
|
* When this mode may be armed. Absent / null = always allowed (same as a
|
|
40239
40240
|
* rule with no `schedule`). Evaluated with {@link isScheduleActive}.
|
|
40240
40241
|
*/
|
|
40241
|
-
schedule: NcScheduleSchema.optional()
|
|
40242
|
+
schedule: NcScheduleSchema.optional(),
|
|
40243
|
+
/**
|
|
40244
|
+
* D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
|
|
40245
|
+
* intrusion naming the locations)? Absent = false — the entry-delay notification is the
|
|
40246
|
+
* only one, and the matches ride the triggered notification's mosaic (D705).
|
|
40247
|
+
*/
|
|
40248
|
+
notifyDuringEntryDelay: zod.z.boolean().optional(),
|
|
40249
|
+
/**
|
|
40250
|
+
* D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
|
|
40251
|
+
* Absent = false (logged, not sent). Even when true it is not sent when that same sensor
|
|
40252
|
+
* is the one that starts the entry delay — the entry-delay notification already names it.
|
|
40253
|
+
*/
|
|
40254
|
+
notifySensorRewatched: zod.z.boolean().optional()
|
|
40242
40255
|
});
|
|
40243
40256
|
var NcAlarmModeDelaysListSchema = zod.z.array(NcAlarmModeDelaysSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
40244
40257
|
var NcAlarmModeDelaysEditSchema = zod.z.object({
|
|
@@ -40248,7 +40261,11 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
40248
40261
|
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
|
|
40249
40262
|
postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
|
|
40250
40263
|
/** Set a schedule, or `null` to clear (mode always allowed again). */
|
|
40251
|
-
schedule: NcScheduleSchema.nullable().optional()
|
|
40264
|
+
schedule: NcScheduleSchema.nullable().optional(),
|
|
40265
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
40266
|
+
notifyDuringEntryDelay: zod.z.boolean().nullable().optional(),
|
|
40267
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
40268
|
+
notifySensorRewatched: zod.z.boolean().nullable().optional()
|
|
40252
40269
|
});
|
|
40253
40270
|
var NcAlarmModeDelaysEditListSchema = zod.z.array(NcAlarmModeDelaysEditSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
40254
40271
|
var NcAlarmNonBlockingEditSchema = zod.z.object({
|
|
@@ -44218,6 +44235,11 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
44218
44235
|
"analyzer",
|
|
44219
44236
|
"device-activity"
|
|
44220
44237
|
]);
|
|
44238
|
+
var SessionTriggerSchema = zod.z.object({
|
|
44239
|
+
source: MotionSourceEnum,
|
|
44240
|
+
triggeredBy: MotionTriggeredBySchema,
|
|
44241
|
+
sensorName: zod.z.string().optional()
|
|
44242
|
+
});
|
|
44221
44243
|
var MotionSourcesSchema = zod.z.array(MotionSourceEnum);
|
|
44222
44244
|
var MOTION_SOURCE_LABELS = {
|
|
44223
44245
|
analyzer: "Frame-diff Analyzer (motion addon)",
|
|
@@ -44365,6 +44387,14 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
44365
44387
|
*/
|
|
44366
44388
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
44367
44389
|
/**
|
|
44390
|
+
* What opened this attach, on a SESSION attach only (see
|
|
44391
|
+
* {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
|
|
44392
|
+
* standing attach, an occupancy burst, a re-dispatch with no motion event
|
|
44393
|
+
* behind it, and every attach from an orchestrator older than the field — the
|
|
44394
|
+
* runner then names no source on the phase event.
|
|
44395
|
+
*/
|
|
44396
|
+
sessionTrigger: SessionTriggerSchema.optional(),
|
|
44397
|
+
/**
|
|
44368
44398
|
* WHICH root detector runs for this camera. The detection counterpart of
|
|
44369
44399
|
* {@link motionSources}, same shape and same discipline: a per-camera list
|
|
44370
44400
|
* of sources the system understands, vendor-agnostic, owned here.
|
|
@@ -48105,6 +48135,36 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
48105
48135
|
})
|
|
48106
48136
|
}
|
|
48107
48137
|
};
|
|
48138
|
+
var CAMSTACK_APP_LINK_ORIGIN = "https://camstack.zentik.app";
|
|
48139
|
+
function toAppLinkHubOrigin(baseUrl) {
|
|
48140
|
+
let parsed;
|
|
48141
|
+
try {
|
|
48142
|
+
parsed = new URL(baseUrl);
|
|
48143
|
+
} catch {
|
|
48144
|
+
return null;
|
|
48145
|
+
}
|
|
48146
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return null;
|
|
48147
|
+
if (parsed.username !== "" || parsed.password !== "") return null;
|
|
48148
|
+
if (parsed.hostname === "") return null;
|
|
48149
|
+
return parsed.origin;
|
|
48150
|
+
}
|
|
48151
|
+
function pickAppLinkHub(endpoints) {
|
|
48152
|
+
const rank2 = (e) => {
|
|
48153
|
+
if (e.kind !== "public" || !e.baseUrl.startsWith("https://")) return null;
|
|
48154
|
+
if (e.interfaceKind === "public") return 0;
|
|
48155
|
+
if (e.interfaceKind === "vpn") return 1;
|
|
48156
|
+
return null;
|
|
48157
|
+
};
|
|
48158
|
+
return endpoints.flatMap((e) => {
|
|
48159
|
+
const r = rank2(e);
|
|
48160
|
+
const origin = toAppLinkHubOrigin(e.baseUrl);
|
|
48161
|
+
return r === null || origin === null ? [] : [{
|
|
48162
|
+
r,
|
|
48163
|
+
p: e.priority,
|
|
48164
|
+
origin
|
|
48165
|
+
}];
|
|
48166
|
+
}).toSorted((a, b) => a.r - b.r || a.p - b.p)[0]?.origin ?? null;
|
|
48167
|
+
}
|
|
48108
48168
|
var webrtcClientHintsSchema = zod.z.object({
|
|
48109
48169
|
viewportWidth: zod.z.number().int().positive().optional(),
|
|
48110
48170
|
viewportHeight: zod.z.number().int().positive().optional(),
|
|
@@ -51947,7 +52007,7 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
51947
52007
|
name: zod.z.string(),
|
|
51948
52008
|
family: zod.z.enum(["IPv4", "IPv6"]),
|
|
51949
52009
|
address: zod.z.string(),
|
|
51950
|
-
/** CIDR shorthand (e.g. `192.168.
|
|
52010
|
+
/** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
|
|
51951
52011
|
cidr: zod.z.string(),
|
|
51952
52012
|
/** OS netmask. Stable across calls so the SDK can hash on it. */
|
|
51953
52013
|
netmask: zod.z.string(),
|
|
@@ -51996,7 +52056,8 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
51996
52056
|
"lan-ipv4",
|
|
51997
52057
|
"lan-ipv6",
|
|
51998
52058
|
"public",
|
|
51999
|
-
"loopback"
|
|
52059
|
+
"loopback",
|
|
52060
|
+
"app-link"
|
|
52000
52061
|
]),
|
|
52001
52062
|
/**
|
|
52002
52063
|
* Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
|
|
@@ -52061,8 +52122,20 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
52061
52122
|
var NotificationEndpointSchema = zod.z.object({
|
|
52062
52123
|
/** The operator's explicit choice, or null for AUTO. */
|
|
52063
52124
|
baseUrl: zod.z.string().nullable(),
|
|
52064
|
-
/**
|
|
52065
|
-
|
|
52125
|
+
/**
|
|
52126
|
+
* The effective flagged address: the explicit choice, else (AUTO) the
|
|
52127
|
+
* CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
|
|
52128
|
+
* answered the public tunnel / mesh here, or null.
|
|
52129
|
+
*/
|
|
52130
|
+
resolved: zod.z.string().nullable(),
|
|
52131
|
+
/**
|
|
52132
|
+
* The hub origin an app link carries as `hub=` (D709): the hub's best
|
|
52133
|
+
* public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
|
|
52134
|
+
* picked from this cap's own palette by `pickAppLinkHub`. `null` when the
|
|
52135
|
+
* hub advertises neither; the app link is then minted without `hub=`.
|
|
52136
|
+
* Absent on a pre-D709 hub.
|
|
52137
|
+
*/
|
|
52138
|
+
appLinkHub: zod.z.string().nullable()
|
|
52066
52139
|
});
|
|
52067
52140
|
var ViewerEndpointsSchema = zod.z.object({
|
|
52068
52141
|
/** The operator's explicit race set, or empty for AUTO. */
|
|
@@ -52126,7 +52199,7 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
52126
52199
|
* every client a second authority on a socket only the hub binds. A viewer
|
|
52127
52200
|
* configured with a port-less public URL (`https://camstack.example.top`)
|
|
52128
52201
|
* infers 443 from the scheme, asks with 443, and was handed
|
|
52129
|
-
* `https://192.168.
|
|
52202
|
+
* `https://192.168.10.9:443` for a hub listening on 4443. That candidate
|
|
52130
52203
|
* cannot ever answer, and losing its race reads in the log exactly like
|
|
52131
52204
|
* "the LAN was tried and it was slower" — so an operator sitting on his own
|
|
52132
52205
|
* WiFi stayed on the public tunnel for weeks, with the LAN candidate born
|
|
@@ -52159,13 +52232,21 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
52159
52232
|
* Pass `'https'` when the caller is itself loaded over HTTPS
|
|
52160
52233
|
* to avoid mixed-content blocks in the browser. The public
|
|
52161
52234
|
* tunnel always emits `https://` regardless. */
|
|
52162
|
-
scheme: zod.z.enum(["http", "https"]).optional()
|
|
52235
|
+
scheme: zod.z.enum(["http", "https"]).optional(),
|
|
52236
|
+
/** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
|
|
52237
|
+
* an address notification links can be flagged with, not a hub
|
|
52238
|
+
* route. Default `false`: racers and rankers never see it. */
|
|
52239
|
+
includeAppLink: zod.z.boolean().optional()
|
|
52163
52240
|
}), GetConnectionEndpointsResultSchema),
|
|
52164
52241
|
/**
|
|
52165
|
-
* The
|
|
52166
|
-
*
|
|
52167
|
-
*
|
|
52168
|
-
*
|
|
52242
|
+
* The address notification links are flagged with. `baseUrl: null` means
|
|
52243
|
+
* AUTO, which is the CamStack app link (D709): viewer taps go through
|
|
52244
|
+
* `https://camstack.zentik.app/…?hub=<appLinkHub>` and open the app. Any
|
|
52245
|
+
* hub address the palette lists can be flagged instead; then viewer taps,
|
|
52246
|
+
* attachment links and action buttons all use it. Signed media and
|
|
52247
|
+
* buttons never use the app link — with it flagged (or AUTO) they keep
|
|
52248
|
+
* the ranked hub ladder (a configured origin, a connected tunnel, then
|
|
52249
|
+
* the LAN), never loopback.
|
|
52169
52250
|
*
|
|
52170
52251
|
* Why an explicit marker: the automatic ranking cannot know which of
|
|
52171
52252
|
* several reachable addresses the RECIPIENT can actually open. A link is
|
|
@@ -52524,7 +52605,7 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
52524
52605
|
tags: zod.z.array(zod.z.string()).readonly(),
|
|
52525
52606
|
/** True when the peer advertises itself as an exit-node candidate. */
|
|
52526
52607
|
exitNodeOption: zod.z.boolean(),
|
|
52527
|
-
/** Subnet routes the peer advertises (e.g. `["192.168.
|
|
52608
|
+
/** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
|
|
52528
52609
|
advertisedRoutes: zod.z.array(zod.z.string()).readonly(),
|
|
52529
52610
|
/** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
|
|
52530
52611
|
userLogin: zod.z.string().nullable(),
|
|
@@ -72192,12 +72273,14 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
72192
72273
|
{
|
|
72193
72274
|
id: "addons",
|
|
72194
72275
|
family: "system",
|
|
72195
|
-
label: "Addons",
|
|
72196
|
-
kinds: [
|
|
72197
|
-
|
|
72198
|
-
|
|
72199
|
-
|
|
72200
|
-
|
|
72276
|
+
label: "Addons stopped",
|
|
72277
|
+
kinds: ["addon-crash-loop"]
|
|
72278
|
+
},
|
|
72279
|
+
{
|
|
72280
|
+
id: "addon-updates",
|
|
72281
|
+
family: "system",
|
|
72282
|
+
label: "Addon updates",
|
|
72283
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
72201
72284
|
},
|
|
72202
72285
|
{
|
|
72203
72286
|
id: "updates",
|
|
@@ -72327,13 +72410,15 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
72327
72410
|
},
|
|
72328
72411
|
{
|
|
72329
72412
|
name: "summaryAddons",
|
|
72330
|
-
label: "Summary: addons",
|
|
72331
|
-
example: "
|
|
72332
|
-
kinds: [
|
|
72333
|
-
|
|
72334
|
-
|
|
72335
|
-
|
|
72336
|
-
|
|
72413
|
+
label: "Summary: addons stopped",
|
|
72414
|
+
example: "hub \u2014 recorder stopped after repeated crashes",
|
|
72415
|
+
kinds: ["addon-crash-loop"]
|
|
72416
|
+
},
|
|
72417
|
+
{
|
|
72418
|
+
name: "summaryAddonUpdates",
|
|
72419
|
+
label: "Summary: addon updates",
|
|
72420
|
+
example: "hub:\n\u2022 @camstack/addon-recorder 1.2.3 \u2192 1.2.4",
|
|
72421
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
72337
72422
|
},
|
|
72338
72423
|
{
|
|
72339
72424
|
name: "summaryUpdates",
|
|
@@ -72417,6 +72502,7 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
72417
72502
|
[...RULE_BODY_ONLY],
|
|
72418
72503
|
[...RULE_TEXT],
|
|
72419
72504
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
72505
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
72420
72506
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
72421
72507
|
([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
|
|
72422
72508
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
@@ -72868,6 +72954,12 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
72868
72954
|
return CAMERA_SWITCH_ORDER;
|
|
72869
72955
|
}
|
|
72870
72956
|
});
|
|
72957
|
+
Object.defineProperty(exports, "CAMSTACK_APP_LINK_ORIGIN", {
|
|
72958
|
+
enumerable: true,
|
|
72959
|
+
get: function() {
|
|
72960
|
+
return CAMSTACK_APP_LINK_ORIGIN;
|
|
72961
|
+
}
|
|
72962
|
+
});
|
|
72871
72963
|
Object.defineProperty(exports, "CAP_NAMES_WITH_STATUS", {
|
|
72872
72964
|
enumerable: true,
|
|
72873
72965
|
get: function() {
|
|
@@ -73702,6 +73794,12 @@ var require_dist_CXVXFdJX = __commonJS({
|
|
|
73702
73794
|
return parseStreamParamsFormPatch;
|
|
73703
73795
|
}
|
|
73704
73796
|
});
|
|
73797
|
+
Object.defineProperty(exports, "pickAppLinkHub", {
|
|
73798
|
+
enumerable: true,
|
|
73799
|
+
get: function() {
|
|
73800
|
+
return pickAppLinkHub;
|
|
73801
|
+
}
|
|
73802
|
+
});
|
|
73705
73803
|
Object.defineProperty(exports, "planComposition", {
|
|
73706
73804
|
enumerable: true,
|
|
73707
73805
|
get: function() {
|
|
@@ -73930,7 +74028,7 @@ var require_alerts_addon = __commonJS({
|
|
|
73930
74028
|
[Symbol.toStringTag]: { value: "Module" }
|
|
73931
74029
|
});
|
|
73932
74030
|
require_chunk_Cek0wNdY();
|
|
73933
|
-
var require_dist10 =
|
|
74031
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
73934
74032
|
function deviceLabelFromEventData(data) {
|
|
73935
74033
|
const name = stringNonEmpty(data["name"]) ?? stringNonEmpty(data["deviceName"]);
|
|
73936
74034
|
if (name !== void 0) return name;
|
|
@@ -74754,7 +74852,7 @@ var require_calendars_addon = __commonJS({
|
|
|
74754
74852
|
[Symbol.toStringTag]: { value: "Module" }
|
|
74755
74853
|
});
|
|
74756
74854
|
require_chunk_Cek0wNdY();
|
|
74757
|
-
var require_dist10 =
|
|
74855
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
74758
74856
|
var require_settle_sources = require_settle_sources_Bhsy57y();
|
|
74759
74857
|
var zod = require_zod();
|
|
74760
74858
|
var CALENDAR_COLOR_PALETTE = [
|
|
@@ -74968,11 +75066,11 @@ var require_calendars = __commonJS({
|
|
|
74968
75066
|
}
|
|
74969
75067
|
});
|
|
74970
75068
|
|
|
74971
|
-
// ../system/dist/composition-sources-
|
|
74972
|
-
var
|
|
74973
|
-
"../system/dist/composition-sources-
|
|
75069
|
+
// ../system/dist/composition-sources-0nuWOdNd.js
|
|
75070
|
+
var require_composition_sources_0nuWOdNd = __commonJS({
|
|
75071
|
+
"../system/dist/composition-sources-0nuWOdNd.js"(exports) {
|
|
74974
75072
|
"use strict";
|
|
74975
|
-
var require_dist10 =
|
|
75073
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
74976
75074
|
function normalizedNativeOwner(owner) {
|
|
74977
75075
|
const trimmed = owner?.trim();
|
|
74978
75076
|
return trimmed ? trimmed : null;
|
|
@@ -75087,8 +75185,8 @@ var require_composer_addon = __commonJS({
|
|
|
75087
75185
|
[Symbol.toStringTag]: { value: "Module" }
|
|
75088
75186
|
});
|
|
75089
75187
|
require_chunk_Cek0wNdY();
|
|
75090
|
-
var require_dist10 =
|
|
75091
|
-
var require_composition_sources =
|
|
75188
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
75189
|
+
var require_composition_sources = require_composition_sources_0nuWOdNd();
|
|
75092
75190
|
var zod = require_zod();
|
|
75093
75191
|
function isRecord$2(value) {
|
|
75094
75192
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -76138,6 +76236,10 @@ var require_composer_addon = __commonJS({
|
|
|
76138
76236
|
value: outcome.value
|
|
76139
76237
|
};
|
|
76140
76238
|
}
|
|
76239
|
+
function hasObservedRoseLevel(memory) {
|
|
76240
|
+
for (const call of memory.calls.values()) if (call.kind === "rose" && call.priorLevel !== void 0) return true;
|
|
76241
|
+
return false;
|
|
76242
|
+
}
|
|
76141
76243
|
function strictFiniteAdvance(previous, next) {
|
|
76142
76244
|
return typeof next === "number" && Number.isFinite(next) && (previous === null || next > previous);
|
|
76143
76245
|
}
|
|
@@ -76177,7 +76279,7 @@ var require_composer_addon = __commonJS({
|
|
|
76177
76279
|
const record = next.get(key);
|
|
76178
76280
|
if (record === void 0) continue;
|
|
76179
76281
|
const candidateMemory = require_dist10.cloneStatefulExpressionMemory(record.expressionMemory);
|
|
76180
|
-
if (record.outcome?.state === "unavailable") require_dist10.disarmRoseMemory(candidateMemory);
|
|
76282
|
+
if (record.outcome?.state === "unavailable" && hasObservedRoseLevel(record.expressionMemory)) require_dist10.disarmRoseMemory(candidateMemory);
|
|
76181
76283
|
const outcome = require_dist10.evaluateCompositionField({
|
|
76182
76284
|
source: record.plan.source,
|
|
76183
76285
|
read,
|
|
@@ -78871,7 +78973,7 @@ var require_console_logging = __commonJS({
|
|
|
78871
78973
|
[Symbol.toStringTag]: { value: "Module" }
|
|
78872
78974
|
});
|
|
78873
78975
|
require_chunk_Cek0wNdY();
|
|
78874
|
-
var require_dist10 =
|
|
78976
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
78875
78977
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
78876
78978
|
var LEVEL_RANK = {
|
|
78877
78979
|
debug: 0,
|
|
@@ -82940,8 +83042,8 @@ var require_core_blocks_addon = __commonJS({
|
|
|
82940
83042
|
"use strict";
|
|
82941
83043
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
82942
83044
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
82943
|
-
var require_dist10 =
|
|
82944
|
-
var require_composition_sources =
|
|
83045
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
83046
|
+
var require_composition_sources = require_composition_sources_0nuWOdNd();
|
|
82945
83047
|
var node_crypto = __require("crypto");
|
|
82946
83048
|
var _camstack_types_node = require_node();
|
|
82947
83049
|
var node_fs_promises = __require("fs/promises");
|
|
@@ -84813,11 +84915,11 @@ var require_core_blocks = __commonJS({
|
|
|
84813
84915
|
}
|
|
84814
84916
|
});
|
|
84815
84917
|
|
|
84816
|
-
// ../system/dist/retired-settings-keys-
|
|
84817
|
-
var
|
|
84818
|
-
"../system/dist/retired-settings-keys-
|
|
84918
|
+
// ../system/dist/retired-settings-keys-BTKZdPn6.js
|
|
84919
|
+
var require_retired_settings_keys_BTKZdPn6 = __commonJS({
|
|
84920
|
+
"../system/dist/retired-settings-keys-BTKZdPn6.js"(exports) {
|
|
84819
84921
|
"use strict";
|
|
84820
|
-
var require_dist10 =
|
|
84922
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
84821
84923
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
84822
84924
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
84823
84925
|
return raw === "" || raw === "hub";
|
|
@@ -85106,8 +85208,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
85106
85208
|
[Symbol.toStringTag]: { value: "Module" }
|
|
85107
85209
|
});
|
|
85108
85210
|
require_chunk_Cek0wNdY();
|
|
85109
|
-
var require_dist10 =
|
|
85110
|
-
var require_retired_settings_keys =
|
|
85211
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
85212
|
+
var require_retired_settings_keys = require_retired_settings_keys_BTKZdPn6();
|
|
85111
85213
|
var zod = require_zod();
|
|
85112
85214
|
var node_crypto = __require("crypto");
|
|
85113
85215
|
var _camstack_types_node = require_node();
|
|
@@ -93302,7 +93404,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
93302
93404
|
[Symbol.toStringTag]: { value: "Module" }
|
|
93303
93405
|
});
|
|
93304
93406
|
require_chunk_Cek0wNdY();
|
|
93305
|
-
var require_dist10 =
|
|
93407
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
93306
93408
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
93307
93409
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
93308
93410
|
var HubForwarderDestination = class {
|
|
@@ -93439,7 +93541,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
93439
93541
|
"use strict";
|
|
93440
93542
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
93441
93543
|
require_chunk_Cek0wNdY();
|
|
93442
|
-
var require_dist10 =
|
|
93544
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
93443
93545
|
var NO_DEVICES = "liveness:no-devices";
|
|
93444
93546
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
93445
93547
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -93655,7 +93757,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
93655
93757
|
[Symbol.toStringTag]: { value: "Module" }
|
|
93656
93758
|
});
|
|
93657
93759
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
93658
|
-
var require_dist10 =
|
|
93760
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
93659
93761
|
var node_crypto = __require("crypto");
|
|
93660
93762
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
93661
93763
|
var crypto$1 = __require("crypto");
|
|
@@ -101509,7 +101611,7 @@ var require_loki_logging = __commonJS({
|
|
|
101509
101611
|
[Symbol.toStringTag]: { value: "Module" }
|
|
101510
101612
|
});
|
|
101511
101613
|
require_chunk_Cek0wNdY();
|
|
101512
|
-
var require_dist10 =
|
|
101614
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
101513
101615
|
function sanitizeLabelName(raw) {
|
|
101514
101616
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
101515
101617
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -102212,7 +102314,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
102212
102314
|
[Symbol.toStringTag]: { value: "Module" }
|
|
102213
102315
|
});
|
|
102214
102316
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
102215
|
-
var require_dist10 =
|
|
102317
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
102216
102318
|
var require_proc_stat = require_proc_stat_DL_WUOhl();
|
|
102217
102319
|
var node_fs_promises = __require("fs/promises");
|
|
102218
102320
|
var node_os = __require("os");
|
|
@@ -105052,7 +105154,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
105052
105154
|
[Symbol.toStringTag]: { value: "Module" }
|
|
105053
105155
|
});
|
|
105054
105156
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
105055
|
-
var require_dist10 =
|
|
105157
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
105056
105158
|
var node_crypto = __require("crypto");
|
|
105057
105159
|
var node_fs_promises = __require("fs/promises");
|
|
105058
105160
|
var node_path = __require("path");
|
|
@@ -106334,8 +106436,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
106334
106436
|
[Symbol.toStringTag]: { value: "Module" }
|
|
106335
106437
|
});
|
|
106336
106438
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
106337
|
-
var require_dist10 =
|
|
106338
|
-
var require_retired_settings_keys =
|
|
106439
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
106440
|
+
var require_retired_settings_keys = require_retired_settings_keys_BTKZdPn6();
|
|
106339
106441
|
var require_sqlite_snapshot_protocol = require_sqlite_snapshot_protocol_B9OndqZv();
|
|
106340
106442
|
var require_wal_checkpoint_policy = require_wal_checkpoint_policy_d2z2qPqx();
|
|
106341
106443
|
var node_crypto = __require("crypto");
|
|
@@ -109531,7 +109633,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
109531
109633
|
[Symbol.toStringTag]: { value: "Module" }
|
|
109532
109634
|
});
|
|
109533
109635
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
109534
|
-
var require_dist10 =
|
|
109636
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
109535
109637
|
var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
|
|
109536
109638
|
var zod = require_zod();
|
|
109537
109639
|
var node_crypto = __require("crypto");
|
|
@@ -113258,7 +113360,7 @@ var require_system_config_addon = __commonJS({
|
|
|
113258
113360
|
[Symbol.toStringTag]: { value: "Module" }
|
|
113259
113361
|
});
|
|
113260
113362
|
require_chunk_Cek0wNdY();
|
|
113261
|
-
var require_dist10 =
|
|
113363
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
113262
113364
|
var SECTION_TITLES = {
|
|
113263
113365
|
server: "Server",
|
|
113264
113366
|
auth: "Authentication"
|
|
@@ -131319,7 +131421,7 @@ var require_winston_logging = __commonJS({
|
|
|
131319
131421
|
[Symbol.toStringTag]: { value: "Module" }
|
|
131320
131422
|
});
|
|
131321
131423
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
131322
|
-
var require_dist10 =
|
|
131424
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
131323
131425
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
131324
131426
|
var node_path = __require("path");
|
|
131325
131427
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -154984,12 +155086,12 @@ var require_dist2 = __commonJS({
|
|
|
154984
155086
|
}
|
|
154985
155087
|
});
|
|
154986
155088
|
|
|
154987
|
-
// ../system/dist/child-cap-dispatch-
|
|
154988
|
-
var
|
|
154989
|
-
"../system/dist/child-cap-dispatch-
|
|
155089
|
+
// ../system/dist/child-cap-dispatch-CRqYKHAb.js
|
|
155090
|
+
var require_child_cap_dispatch_CRqYKHAb = __commonJS({
|
|
155091
|
+
"../system/dist/child-cap-dispatch-CRqYKHAb.js"(exports) {
|
|
154990
155092
|
"use strict";
|
|
154991
155093
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
154992
|
-
var require_dist10 =
|
|
155094
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
154993
155095
|
var require_proc_stat = require_proc_stat_DL_WUOhl();
|
|
154994
155096
|
require_hub_cap_forward_DmHNjbB0();
|
|
154995
155097
|
var node_crypto = __require("crypto");
|
|
@@ -169528,7 +169630,7 @@ var require_dist3 = __commonJS({
|
|
|
169528
169630
|
"use strict";
|
|
169529
169631
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
169530
169632
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
169531
|
-
var require_dist10 =
|
|
169633
|
+
var require_dist10 = require_dist_DePB7uwU();
|
|
169532
169634
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
169533
169635
|
require_alerts();
|
|
169534
169636
|
var require_builtins_calendars_calendars_addon = require_calendars_addon();
|
|
@@ -169559,7 +169661,7 @@ var require_dist3 = __commonJS({
|
|
|
169559
169661
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
169560
169662
|
var require_event_loop_stall_monitor = require_event_loop_stall_monitor_ey4mbofz();
|
|
169561
169663
|
var require_tls$1 = require_tls_ue_Xefmv();
|
|
169562
|
-
var require_child_cap_dispatch =
|
|
169664
|
+
var require_child_cap_dispatch = require_child_cap_dispatch_CRqYKHAb();
|
|
169563
169665
|
var require_resource_monitor = require_resource_monitor_BgWGRxN5();
|
|
169564
169666
|
var require_custom_action_registry = require_custom_action_registry_acBY3mHA();
|
|
169565
169667
|
var zod = require_zod();
|
|
@@ -169874,6 +169976,29 @@ var require_dist3 = __commonJS({
|
|
|
169874
169976
|
function canServeDataPlane(state) {
|
|
169875
169977
|
return state.hasEntry && state.isForked && state.childKnown;
|
|
169876
169978
|
}
|
|
169979
|
+
function edgeOwnedResponseHeaders(upRes, clientRes) {
|
|
169980
|
+
const out = {};
|
|
169981
|
+
for (const [name2, value] of Object.entries(upRes.headers)) {
|
|
169982
|
+
if (value === void 0) continue;
|
|
169983
|
+
const lower = name2.toLowerCase();
|
|
169984
|
+
if (lower.startsWith("access-control-")) continue;
|
|
169985
|
+
out[lower] = value;
|
|
169986
|
+
}
|
|
169987
|
+
const edgeVary = clientRes.getHeader("vary");
|
|
169988
|
+
const upVary = out["vary"];
|
|
169989
|
+
if (typeof edgeVary === "string" && edgeVary.length > 0 && upVary !== void 0) {
|
|
169990
|
+
const tokens = /* @__PURE__ */ new Set();
|
|
169991
|
+
const merged = [];
|
|
169992
|
+
for (const part of [edgeVary, String(upVary)].join(",").split(",")) {
|
|
169993
|
+
const token2 = part.trim();
|
|
169994
|
+
if (token2.length === 0 || tokens.has(token2.toLowerCase())) continue;
|
|
169995
|
+
tokens.add(token2.toLowerCase());
|
|
169996
|
+
merged.push(token2);
|
|
169997
|
+
}
|
|
169998
|
+
out["vary"] = merged.join(", ");
|
|
169999
|
+
}
|
|
170000
|
+
return out;
|
|
170001
|
+
}
|
|
169877
170002
|
function proxyToUpstream(opts) {
|
|
169878
170003
|
const { baseUrl, secret, upstreamPath, clientReq, clientRes, replayBody } = opts;
|
|
169879
170004
|
const base = new URL(baseUrl);
|
|
@@ -169891,17 +170016,11 @@ var require_dist3 = __commonJS({
|
|
|
169891
170016
|
path: upstreamPath,
|
|
169892
170017
|
headers
|
|
169893
170018
|
}, (upRes) => {
|
|
169894
|
-
clientRes.writeHead(upRes.statusCode ?? 502,
|
|
169895
|
-
"access-control-allow-origin": "*",
|
|
169896
|
-
...upRes.headers
|
|
169897
|
-
});
|
|
170019
|
+
clientRes.writeHead(upRes.statusCode ?? 502, edgeOwnedResponseHeaders(upRes, clientRes));
|
|
169898
170020
|
upRes.pipe(clientRes);
|
|
169899
170021
|
});
|
|
169900
170022
|
upstream.on("error", (err) => {
|
|
169901
|
-
if (!clientRes.headersSent) clientRes.writeHead(502, {
|
|
169902
|
-
"content-type": "application/json",
|
|
169903
|
-
"access-control-allow-origin": "*"
|
|
169904
|
-
});
|
|
170023
|
+
if (!clientRes.headersSent) clientRes.writeHead(502, { "content-type": "application/json" });
|
|
169905
170024
|
clientRes.end(JSON.stringify({
|
|
169906
170025
|
error: "data-plane upstream error",
|
|
169907
170026
|
detail: String(err)
|
|
@@ -176139,10 +176258,19 @@ var require_dist3 = __commonJS({
|
|
|
176139
176258
|
};
|
|
176140
176259
|
}
|
|
176141
176260
|
var DEFAULT_DATA_PATH = "camstack-data";
|
|
176261
|
+
var originListSchema = zod.z.preprocess((value) => typeof value === "string" ? value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0) : value, zod.z.array(zod.z.string()));
|
|
176142
176262
|
var serverSchema = zod.z.object({
|
|
176143
176263
|
port: zod.z.number().default(4443),
|
|
176144
176264
|
host: zod.z.string().default("0.0.0.0"),
|
|
176145
|
-
dataPath: zod.z.string().default(DEFAULT_DATA_PATH)
|
|
176265
|
+
dataPath: zod.z.string().default(DEFAULT_DATA_PATH),
|
|
176266
|
+
/**
|
|
176267
|
+
* EXTRA browser origins allowed to call this hub cross-origin (D707), on
|
|
176268
|
+
* top of the built-ins: the hub's own origin, the hosted viewer PWA and the
|
|
176269
|
+
* native app's opaque `null` origin. Bootstrap-owned on purpose — widening
|
|
176270
|
+
* who may read hub responses in a browser is a security decision, and the
|
|
176271
|
+
* policy is live from the first request, before the settings store exists.
|
|
176272
|
+
*/
|
|
176273
|
+
corsOrigins: originListSchema.default([])
|
|
176146
176274
|
});
|
|
176147
176275
|
var authSchema = zod.z.object({
|
|
176148
176276
|
jwtSecret: zod.z.string().nullable().default(null),
|
|
@@ -178612,7 +178740,8 @@ var require_dist3 = __commonJS({
|
|
|
178612
178740
|
CAMSTACK_DATA: "server.dataPath",
|
|
178613
178741
|
CAMSTACK_JWT_SECRET: "auth.jwtSecret",
|
|
178614
178742
|
CAMSTACK_ADMIN_USER: "auth.adminUsername",
|
|
178615
|
-
CAMSTACK_ADMIN_PASS: "auth.adminPassword"
|
|
178743
|
+
CAMSTACK_ADMIN_PASS: "auth.adminPassword",
|
|
178744
|
+
CAMSTACK_CORS_ORIGINS: "server.corsOrigins"
|
|
178616
178745
|
};
|
|
178617
178746
|
function loadBootstrapConfig(configPath) {
|
|
178618
178747
|
const merged = applyEnvOverrides((0, _camstack_types_addon.asJsonObject)(loadYaml(configPath)) ?? {});
|
|
@@ -266129,6 +266258,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
266129
266258
|
"detection-blind",
|
|
266130
266259
|
"nodes",
|
|
266131
266260
|
"addons",
|
|
266261
|
+
"addon-updates",
|
|
266132
266262
|
"updates"
|
|
266133
266263
|
]);
|
|
266134
266264
|
var NcStateSummaryPreviewSectionSchema = zod.z.object({
|
|
@@ -267051,7 +267181,19 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
267051
267181
|
* When this mode may be armed. Absent / null = always allowed (same as a
|
|
267052
267182
|
* rule with no `schedule`). Evaluated with {@link isScheduleActive}.
|
|
267053
267183
|
*/
|
|
267054
|
-
schedule: NcScheduleSchema.optional()
|
|
267184
|
+
schedule: NcScheduleSchema.optional(),
|
|
267185
|
+
/**
|
|
267186
|
+
* D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
|
|
267187
|
+
* intrusion naming the locations)? Absent = false — the entry-delay notification is the
|
|
267188
|
+
* only one, and the matches ride the triggered notification's mosaic (D705).
|
|
267189
|
+
*/
|
|
267190
|
+
notifyDuringEntryDelay: zod.z.boolean().optional(),
|
|
267191
|
+
/**
|
|
267192
|
+
* D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
|
|
267193
|
+
* Absent = false (logged, not sent). Even when true it is not sent when that same sensor
|
|
267194
|
+
* is the one that starts the entry delay — the entry-delay notification already names it.
|
|
267195
|
+
*/
|
|
267196
|
+
notifySensorRewatched: zod.z.boolean().optional()
|
|
267055
267197
|
});
|
|
267056
267198
|
var NcAlarmModeDelaysListSchema = zod.z.array(NcAlarmModeDelaysSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
267057
267199
|
var NcAlarmModeDelaysEditSchema = zod.z.object({
|
|
@@ -267061,7 +267203,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
267061
267203
|
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
|
|
267062
267204
|
postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
|
|
267063
267205
|
/** Set a schedule, or `null` to clear (mode always allowed again). */
|
|
267064
|
-
schedule: NcScheduleSchema.nullable().optional()
|
|
267206
|
+
schedule: NcScheduleSchema.nullable().optional(),
|
|
267207
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
267208
|
+
notifyDuringEntryDelay: zod.z.boolean().nullable().optional(),
|
|
267209
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
267210
|
+
notifySensorRewatched: zod.z.boolean().nullable().optional()
|
|
267065
267211
|
});
|
|
267066
267212
|
var NcAlarmModeDelaysEditListSchema = zod.z.array(NcAlarmModeDelaysEditSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
267067
267213
|
var NcAlarmNonBlockingEditSchema = zod.z.object({
|
|
@@ -271148,6 +271294,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
271148
271294
|
"analyzer",
|
|
271149
271295
|
"device-activity"
|
|
271150
271296
|
]);
|
|
271297
|
+
var SessionTriggerSchema = zod.z.object({
|
|
271298
|
+
source: MotionSourceEnum,
|
|
271299
|
+
triggeredBy: MotionTriggeredBySchema,
|
|
271300
|
+
sensorName: zod.z.string().optional()
|
|
271301
|
+
});
|
|
271151
271302
|
var MotionSourcesSchema = zod.z.array(MotionSourceEnum);
|
|
271152
271303
|
var MOTION_SOURCE_LABELS = {
|
|
271153
271304
|
analyzer: "Frame-diff Analyzer (motion addon)",
|
|
@@ -271299,6 +271450,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
271299
271450
|
*/
|
|
271300
271451
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
271301
271452
|
/**
|
|
271453
|
+
* What opened this attach, on a SESSION attach only (see
|
|
271454
|
+
* {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
|
|
271455
|
+
* standing attach, an occupancy burst, a re-dispatch with no motion event
|
|
271456
|
+
* behind it, and every attach from an orchestrator older than the field — the
|
|
271457
|
+
* runner then names no source on the phase event.
|
|
271458
|
+
*/
|
|
271459
|
+
sessionTrigger: SessionTriggerSchema.optional(),
|
|
271460
|
+
/**
|
|
271302
271461
|
* WHICH root detector runs for this camera. The detection counterpart of
|
|
271303
271462
|
* {@link motionSources}, same shape and same discipline: a per-camera list
|
|
271304
271463
|
* of sources the system understands, vendor-agnostic, owned here.
|
|
@@ -275311,6 +275470,94 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
275311
275470
|
rates: CLIP_BROKER_PACED_RATES
|
|
275312
275471
|
}
|
|
275313
275472
|
};
|
|
275473
|
+
var CAMSTACK_APP_LINK_ORIGIN = "https://camstack.zentik.app";
|
|
275474
|
+
var HUB_VIEWER_MOUNT = "/viewer/camstack";
|
|
275475
|
+
function isAppLinkBase(baseUrl) {
|
|
275476
|
+
if (baseUrl === null || baseUrl === void 0 || baseUrl === "") return false;
|
|
275477
|
+
try {
|
|
275478
|
+
return new URL(baseUrl).origin === CAMSTACK_APP_LINK_ORIGIN;
|
|
275479
|
+
} catch {
|
|
275480
|
+
return false;
|
|
275481
|
+
}
|
|
275482
|
+
}
|
|
275483
|
+
function viewerLinkBaseOf(endpoint) {
|
|
275484
|
+
const flagged = endpoint.baseUrl ?? endpoint.resolved;
|
|
275485
|
+
return isAppLinkBase(flagged) ? {
|
|
275486
|
+
form: "app",
|
|
275487
|
+
hubBaseUrl: endpoint.appLinkHub ?? null
|
|
275488
|
+
} : {
|
|
275489
|
+
form: "hub",
|
|
275490
|
+
hubBaseUrl: flagged
|
|
275491
|
+
};
|
|
275492
|
+
}
|
|
275493
|
+
function toAppLinkHubOrigin(baseUrl) {
|
|
275494
|
+
let parsed;
|
|
275495
|
+
try {
|
|
275496
|
+
parsed = new URL(baseUrl);
|
|
275497
|
+
} catch {
|
|
275498
|
+
return null;
|
|
275499
|
+
}
|
|
275500
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return null;
|
|
275501
|
+
if (parsed.username !== "" || parsed.password !== "") return null;
|
|
275502
|
+
if (parsed.hostname === "") return null;
|
|
275503
|
+
return parsed.origin;
|
|
275504
|
+
}
|
|
275505
|
+
function pickAppLinkHub(endpoints) {
|
|
275506
|
+
const rank2 = (e) => {
|
|
275507
|
+
if (e.kind !== "public" || !e.baseUrl.startsWith("https://")) return null;
|
|
275508
|
+
if (e.interfaceKind === "public") return 0;
|
|
275509
|
+
if (e.interfaceKind === "vpn") return 1;
|
|
275510
|
+
return null;
|
|
275511
|
+
};
|
|
275512
|
+
return endpoints.flatMap((e) => {
|
|
275513
|
+
const r = rank2(e);
|
|
275514
|
+
const origin = toAppLinkHubOrigin(e.baseUrl);
|
|
275515
|
+
return r === null || origin === null ? [] : [{
|
|
275516
|
+
r,
|
|
275517
|
+
p: e.priority,
|
|
275518
|
+
origin
|
|
275519
|
+
}];
|
|
275520
|
+
}).toSorted((a, b) => a.r - b.r || a.p - b.p)[0]?.origin ?? null;
|
|
275521
|
+
}
|
|
275522
|
+
function viewerRoute(destination) {
|
|
275523
|
+
switch (destination.kind) {
|
|
275524
|
+
case "camera": {
|
|
275525
|
+
if (!Number.isInteger(destination.deviceId) || destination.deviceId <= 0) return null;
|
|
275526
|
+
const at = destination.atMs;
|
|
275527
|
+
return {
|
|
275528
|
+
path: `/camera/${String(destination.deviceId)}`,
|
|
275529
|
+
query: at !== void 0 && Number.isFinite(at) ? [["at", String(Math.trunc(at))]] : []
|
|
275530
|
+
};
|
|
275531
|
+
}
|
|
275532
|
+
case "events":
|
|
275533
|
+
return {
|
|
275534
|
+
path: "/events",
|
|
275535
|
+
query: []
|
|
275536
|
+
};
|
|
275537
|
+
case "notifications":
|
|
275538
|
+
return {
|
|
275539
|
+
path: "/notifications",
|
|
275540
|
+
query: []
|
|
275541
|
+
};
|
|
275542
|
+
}
|
|
275543
|
+
}
|
|
275544
|
+
function encodeQuery(query) {
|
|
275545
|
+
if (query.length === 0) return "";
|
|
275546
|
+
return `?${query.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&")}`;
|
|
275547
|
+
}
|
|
275548
|
+
function buildViewerLink(input) {
|
|
275549
|
+
const route = viewerRoute(input.destination);
|
|
275550
|
+
if (route === null) return null;
|
|
275551
|
+
const raw = input.base.hubBaseUrl;
|
|
275552
|
+
const base = raw === null ? "" : raw.replace(/\/+$/, "");
|
|
275553
|
+
if (input.base.form === "app") {
|
|
275554
|
+
const origin = base === "" ? null : toAppLinkHubOrigin(base);
|
|
275555
|
+
const query = origin === null ? route.query : [...route.query, ["hub", origin]];
|
|
275556
|
+
return `${CAMSTACK_APP_LINK_ORIGIN}${route.path}${encodeQuery(query)}`;
|
|
275557
|
+
}
|
|
275558
|
+
if (base === "" || isAppLinkBase(base)) return null;
|
|
275559
|
+
return `${base}${HUB_VIEWER_MOUNT}${route.path}${encodeQuery(route.query)}`;
|
|
275560
|
+
}
|
|
275314
275561
|
var webrtcClientHintsSchema = zod.z.object({
|
|
275315
275562
|
viewportWidth: zod.z.number().int().positive().optional(),
|
|
275316
275563
|
viewportHeight: zod.z.number().int().positive().optional(),
|
|
@@ -279172,7 +279419,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
279172
279419
|
name: zod.z.string(),
|
|
279173
279420
|
family: zod.z.enum(["IPv4", "IPv6"]),
|
|
279174
279421
|
address: zod.z.string(),
|
|
279175
|
-
/** CIDR shorthand (e.g. `192.168.
|
|
279422
|
+
/** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
|
|
279176
279423
|
cidr: zod.z.string(),
|
|
279177
279424
|
/** OS netmask. Stable across calls so the SDK can hash on it. */
|
|
279178
279425
|
netmask: zod.z.string(),
|
|
@@ -279221,7 +279468,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
279221
279468
|
"lan-ipv4",
|
|
279222
279469
|
"lan-ipv6",
|
|
279223
279470
|
"public",
|
|
279224
|
-
"loopback"
|
|
279471
|
+
"loopback",
|
|
279472
|
+
"app-link"
|
|
279225
279473
|
]),
|
|
279226
279474
|
/**
|
|
279227
279475
|
* Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
|
|
@@ -279286,8 +279534,20 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
279286
279534
|
var NotificationEndpointSchema = zod.z.object({
|
|
279287
279535
|
/** The operator's explicit choice, or null for AUTO. */
|
|
279288
279536
|
baseUrl: zod.z.string().nullable(),
|
|
279289
|
-
/**
|
|
279290
|
-
|
|
279537
|
+
/**
|
|
279538
|
+
* The effective flagged address: the explicit choice, else (AUTO) the
|
|
279539
|
+
* CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
|
|
279540
|
+
* answered the public tunnel / mesh here, or null.
|
|
279541
|
+
*/
|
|
279542
|
+
resolved: zod.z.string().nullable(),
|
|
279543
|
+
/**
|
|
279544
|
+
* The hub origin an app link carries as `hub=` (D709): the hub's best
|
|
279545
|
+
* public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
|
|
279546
|
+
* picked from this cap's own palette by `pickAppLinkHub`. `null` when the
|
|
279547
|
+
* hub advertises neither; the app link is then minted without `hub=`.
|
|
279548
|
+
* Absent on a pre-D709 hub.
|
|
279549
|
+
*/
|
|
279550
|
+
appLinkHub: zod.z.string().nullable()
|
|
279291
279551
|
});
|
|
279292
279552
|
var ViewerEndpointsSchema = zod.z.object({
|
|
279293
279553
|
/** The operator's explicit race set, or empty for AUTO. */
|
|
@@ -279351,7 +279611,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
279351
279611
|
* every client a second authority on a socket only the hub binds. A viewer
|
|
279352
279612
|
* configured with a port-less public URL (`https://camstack.example.top`)
|
|
279353
279613
|
* infers 443 from the scheme, asks with 443, and was handed
|
|
279354
|
-
* `https://192.168.
|
|
279614
|
+
* `https://192.168.10.9:443` for a hub listening on 4443. That candidate
|
|
279355
279615
|
* cannot ever answer, and losing its race reads in the log exactly like
|
|
279356
279616
|
* "the LAN was tried and it was slower" — so an operator sitting on his own
|
|
279357
279617
|
* WiFi stayed on the public tunnel for weeks, with the LAN candidate born
|
|
@@ -279384,13 +279644,21 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
279384
279644
|
* Pass `'https'` when the caller is itself loaded over HTTPS
|
|
279385
279645
|
* to avoid mixed-content blocks in the browser. The public
|
|
279386
279646
|
* tunnel always emits `https://` regardless. */
|
|
279387
|
-
scheme: zod.z.enum(["http", "https"]).optional()
|
|
279647
|
+
scheme: zod.z.enum(["http", "https"]).optional(),
|
|
279648
|
+
/** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
|
|
279649
|
+
* an address notification links can be flagged with, not a hub
|
|
279650
|
+
* route. Default `false`: racers and rankers never see it. */
|
|
279651
|
+
includeAppLink: zod.z.boolean().optional()
|
|
279388
279652
|
}), GetConnectionEndpointsResultSchema),
|
|
279389
279653
|
/**
|
|
279390
|
-
* The
|
|
279391
|
-
*
|
|
279392
|
-
*
|
|
279393
|
-
*
|
|
279654
|
+
* The address notification links are flagged with. `baseUrl: null` means
|
|
279655
|
+
* AUTO, which is the CamStack app link (D709): viewer taps go through
|
|
279656
|
+
* `https://camstack.zentik.app/…?hub=<appLinkHub>` and open the app. Any
|
|
279657
|
+
* hub address the palette lists can be flagged instead; then viewer taps,
|
|
279658
|
+
* attachment links and action buttons all use it. Signed media and
|
|
279659
|
+
* buttons never use the app link — with it flagged (or AUTO) they keep
|
|
279660
|
+
* the ranked hub ladder (a configured origin, a connected tunnel, then
|
|
279661
|
+
* the LAN), never loopback.
|
|
279394
279662
|
*
|
|
279395
279663
|
* Why an explicit marker: the automatic ranking cannot know which of
|
|
279396
279664
|
* several reachable addresses the RECIPIENT can actually open. A link is
|
|
@@ -279749,7 +280017,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
279749
280017
|
tags: zod.z.array(zod.z.string()).readonly(),
|
|
279750
280018
|
/** True when the peer advertises itself as an exit-node candidate. */
|
|
279751
280019
|
exitNodeOption: zod.z.boolean(),
|
|
279752
|
-
/** Subnet routes the peer advertises (e.g. `["192.168.
|
|
280020
|
+
/** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
|
|
279753
280021
|
advertisedRoutes: zod.z.array(zod.z.string()).readonly(),
|
|
279754
280022
|
/** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
|
|
279755
280023
|
userLogin: zod.z.string().nullable(),
|
|
@@ -305258,12 +305526,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
305258
305526
|
{
|
|
305259
305527
|
id: "addons",
|
|
305260
305528
|
family: "system",
|
|
305261
|
-
label: "Addons",
|
|
305262
|
-
kinds: [
|
|
305263
|
-
|
|
305264
|
-
|
|
305265
|
-
|
|
305266
|
-
|
|
305529
|
+
label: "Addons stopped",
|
|
305530
|
+
kinds: ["addon-crash-loop"]
|
|
305531
|
+
},
|
|
305532
|
+
{
|
|
305533
|
+
id: "addon-updates",
|
|
305534
|
+
family: "system",
|
|
305535
|
+
label: "Addon updates",
|
|
305536
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
305267
305537
|
},
|
|
305268
305538
|
{
|
|
305269
305539
|
id: "updates",
|
|
@@ -305873,6 +306143,15 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
305873
306143
|
"entryDelaySec",
|
|
305874
306144
|
"triggeredDurationSec"
|
|
305875
306145
|
];
|
|
306146
|
+
var NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC = 30;
|
|
306147
|
+
var NC_ALARM_NOTIFY_FIELDS = ["notifyDuringEntryDelay", "notifySensorRewatched"];
|
|
306148
|
+
function resolveModeNotifyPolicy(settings, mode) {
|
|
306149
|
+
const entry = (settings.modeDelays ?? []).find((e) => e.mode === mode);
|
|
306150
|
+
return {
|
|
306151
|
+
notifyDuringEntryDelay: entry?.notifyDuringEntryDelay === true,
|
|
306152
|
+
notifySensorRewatched: entry?.notifySensorRewatched === true
|
|
306153
|
+
};
|
|
306154
|
+
}
|
|
305876
306155
|
function derivePostTriggeredAction(action, triggeredDurationSec) {
|
|
305877
306156
|
if (action !== void 0) return action;
|
|
305878
306157
|
return triggeredDurationSec > 0 ? "rearmAfter" : "doNothing";
|
|
@@ -305915,6 +306194,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
305915
306194
|
if (edit === void 0) return current;
|
|
305916
306195
|
return edit === null ? void 0 : edit;
|
|
305917
306196
|
}
|
|
306197
|
+
function editedFlag(current, edit) {
|
|
306198
|
+
if (edit === void 0) return current;
|
|
306199
|
+
return edit === null ? void 0 : edit;
|
|
306200
|
+
}
|
|
305918
306201
|
function editedSchedule(current, edit) {
|
|
305919
306202
|
if (edit === void 0) return current;
|
|
305920
306203
|
return edit === null ? void 0 : edit;
|
|
@@ -305945,15 +306228,19 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
305945
306228
|
const triggered = edited(base.triggeredDurationSec, edit.triggeredDurationSec);
|
|
305946
306229
|
const action = editedAction(base.postTriggeredAction, edit.postTriggeredAction);
|
|
305947
306230
|
const schedule = editedSchedule(base.schedule, edit.schedule);
|
|
306231
|
+
const duringEntry = editedFlag(base.notifyDuringEntryDelay, edit.notifyDuringEntryDelay);
|
|
306232
|
+
const rewatched = editedFlag(base.notifySensorRewatched, edit.notifySensorRewatched);
|
|
305948
306233
|
if (exit !== void 0) next.exitDelaySec = exit;
|
|
305949
306234
|
if (entry !== void 0) next.entryDelaySec = entry;
|
|
305950
306235
|
if (triggered !== void 0) next.triggeredDurationSec = triggered;
|
|
305951
306236
|
if (action !== void 0) next.postTriggeredAction = action;
|
|
305952
306237
|
if (schedule !== void 0) next.schedule = schedule;
|
|
306238
|
+
if (duringEntry !== void 0) next.notifyDuringEntryDelay = duringEntry;
|
|
306239
|
+
if (rewatched !== void 0) next.notifySensorRewatched = rewatched;
|
|
305953
306240
|
if (at >= 0) out[at] = next;
|
|
305954
306241
|
else out.push(next);
|
|
305955
306242
|
}
|
|
305956
|
-
return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0 || e.postTriggeredAction !== void 0 || e.schedule !== void 0);
|
|
306243
|
+
return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0 || e.postTriggeredAction !== void 0 || e.schedule !== void 0 || e.notifyDuringEntryDelay !== void 0 || e.notifySensorRewatched !== void 0);
|
|
305957
306244
|
}
|
|
305958
306245
|
function applyModeDeviceListEdit(lists, edit) {
|
|
305959
306246
|
const copy2 = lists.map((l) => ({
|
|
@@ -306080,6 +306367,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
306080
306367
|
const got = entry?.postTriggeredAction;
|
|
306081
306368
|
if (edit.postTriggeredAction === null ? got !== void 0 : got !== edit.postTriggeredAction) return false;
|
|
306082
306369
|
}
|
|
306370
|
+
for (const field of NC_ALARM_NOTIFY_FIELDS) {
|
|
306371
|
+
const want = edit[field];
|
|
306372
|
+
if (want === void 0) continue;
|
|
306373
|
+
const got = entry?.[field];
|
|
306374
|
+
if (want === null ? got !== void 0 : got !== want) return false;
|
|
306375
|
+
}
|
|
306083
306376
|
if (edit.schedule !== void 0) {
|
|
306084
306377
|
const got = entry?.schedule;
|
|
306085
306378
|
if (edit.schedule === null ? got !== void 0 : !sameSchedule(got, edit.schedule)) return false;
|
|
@@ -306418,13 +306711,15 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
306418
306711
|
},
|
|
306419
306712
|
{
|
|
306420
306713
|
name: "summaryAddons",
|
|
306421
|
-
label: "Summary: addons",
|
|
306422
|
-
example: "
|
|
306423
|
-
kinds: [
|
|
306424
|
-
|
|
306425
|
-
|
|
306426
|
-
|
|
306427
|
-
|
|
306714
|
+
label: "Summary: addons stopped",
|
|
306715
|
+
example: "hub \u2014 recorder stopped after repeated crashes",
|
|
306716
|
+
kinds: ["addon-crash-loop"]
|
|
306717
|
+
},
|
|
306718
|
+
{
|
|
306719
|
+
name: "summaryAddonUpdates",
|
|
306720
|
+
label: "Summary: addon updates",
|
|
306721
|
+
example: "hub:\n\u2022 @camstack/addon-recorder 1.2.3 \u2192 1.2.4",
|
|
306722
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
306428
306723
|
},
|
|
306429
306724
|
{
|
|
306430
306725
|
name: "summaryUpdates",
|
|
@@ -306765,6 +307060,16 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
306765
307060
|
kinds: ["system"],
|
|
306766
307061
|
systemEventKinds: [...DEVICE_EVENTS]
|
|
306767
307062
|
},
|
|
307063
|
+
{
|
|
307064
|
+
name: "locations",
|
|
307065
|
+
label: "Intrusion locations",
|
|
307066
|
+
example: "Ingresso, Corridoio, Salone",
|
|
307067
|
+
group: "system",
|
|
307068
|
+
families: ["rule"],
|
|
307069
|
+
fields: [...RULE_TEXT],
|
|
307070
|
+
kinds: ["system"],
|
|
307071
|
+
systemEventKinds: [...COMBINED_ALARM]
|
|
307072
|
+
},
|
|
306768
307073
|
{
|
|
306769
307074
|
name: "deviceId",
|
|
306770
307075
|
label: "Device id",
|
|
@@ -307387,7 +307692,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
307387
307692
|
approximated: times.length > 0
|
|
307388
307693
|
};
|
|
307389
307694
|
}
|
|
307390
|
-
var SUMMARY_CONTENT_VAR = /\{\{\s*summary(?:Text|Devices|Streams|Battery|Consumables|Tanks|Detection|Nodes|Addons|Updates)\s*\}\}/;
|
|
307695
|
+
var SUMMARY_CONTENT_VAR = /\{\{\s*summary(?:Text|Devices|Streams|Battery|Consumables|Tanks|Detection|Nodes|Addons|AddonUpdates|Updates)\s*\}\}/;
|
|
307391
307696
|
function templateCarriesSummary(body) {
|
|
307392
307697
|
if (body === void 0 || body.trim().length === 0) return true;
|
|
307393
307698
|
return SUMMARY_CONTENT_VAR.test(body);
|
|
@@ -309755,6 +310060,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
309755
310060
|
exports.CAMERA_SWITCH_CATALOG = CAMERA_SWITCH_CATALOG;
|
|
309756
310061
|
exports.CAMERA_SWITCH_ORDER = CAMERA_SWITCH_ORDER;
|
|
309757
310062
|
exports.CAMERA_TRIGGER = CAMERA_TRIGGER;
|
|
310063
|
+
exports.CAMSTACK_APP_LINK_ORIGIN = CAMSTACK_APP_LINK_ORIGIN;
|
|
309758
310064
|
exports.CAM_PROFILE_ORDER = require_sleep.CAM_PROFILE_ORDER;
|
|
309759
310065
|
exports.CAPABILITY_NAMES = CAPABILITY_NAMES;
|
|
309760
310066
|
exports.CAPABILITY_ROUTER_KEYS = CAPABILITY_ROUTER_KEYS;
|
|
@@ -310191,6 +310497,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
310191
310497
|
exports.HF_BASE_URL = HF_BASE_URL;
|
|
310192
310498
|
exports.HF_REPO = HF_REPO;
|
|
310193
310499
|
exports.HOURS_PER_DAY = HOURS_PER_DAY;
|
|
310500
|
+
exports.HUB_VIEWER_MOUNT = HUB_VIEWER_MOUNT;
|
|
310194
310501
|
exports.HWACCEL_OPTIONS = HWACCEL_OPTIONS;
|
|
310195
310502
|
exports.HealthStatusSchema = HealthStatusSchema;
|
|
310196
310503
|
exports.HfModelResolutionSchema = HfModelResolutionSchema;
|
|
@@ -310408,9 +310715,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
310408
310715
|
exports.NC_ALARM_CONTROLLABLE_CAPS = NC_ALARM_CONTROLLABLE_CAPS;
|
|
310409
310716
|
exports.NC_ALARM_DEFAULT_PROFILE_ID = NC_ALARM_DEFAULT_PROFILE_ID;
|
|
310410
310717
|
exports.NC_ALARM_DEFAULT_PROFILE_NAME = NC_ALARM_DEFAULT_PROFILE_NAME;
|
|
310718
|
+
exports.NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC = NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC;
|
|
310411
310719
|
exports.NC_ALARM_DELAY_FIELDS = NC_ALARM_DELAY_FIELDS;
|
|
310412
310720
|
exports.NC_ALARM_DELAY_MAX_SEC = NC_ALARM_DELAY_MAX_SEC;
|
|
310413
310721
|
exports.NC_ALARM_NONBLOCKING_MAX = NC_ALARM_NONBLOCKING_MAX;
|
|
310722
|
+
exports.NC_ALARM_NOTIFY_FIELDS = NC_ALARM_NOTIFY_FIELDS;
|
|
310414
310723
|
exports.NC_ALARM_OPENING_EVENT_KINDS = NC_ALARM_OPENING_EVENT_KINDS;
|
|
310415
310724
|
exports.NC_ALARM_SENSORS_MAX = NC_ALARM_SENSORS_MAX;
|
|
310416
310725
|
exports.NC_ALARM_SYSTEM_DEFAULT_DELAYS = NC_ALARM_SYSTEM_DEFAULT_DELAYS;
|
|
@@ -310886,6 +311195,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
310886
311195
|
exports.ServerUpdateCheckResultSchema = ServerUpdateCheckResultSchema;
|
|
310887
311196
|
exports.ServerUpdateOutcomeSchema = ServerUpdateOutcomeSchema;
|
|
310888
311197
|
exports.ServerUpdateStateSchema = ServerUpdateStateSchema;
|
|
311198
|
+
exports.SessionTriggerSchema = SessionTriggerSchema;
|
|
310889
311199
|
exports.SetCameraSensorsInputSchema = SetCameraSensorsInputSchema;
|
|
310890
311200
|
exports.SetLoggingSettingsInputSchema = SetLoggingSettingsInputSchema;
|
|
310891
311201
|
exports.SetSiteLocationInputSchema = SetSiteLocationInputSchema;
|
|
@@ -311169,6 +311479,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
311169
311479
|
exports.buildRoleScopes = buildRoleScopes;
|
|
311170
311480
|
exports.buildStreamParamsConfigSchema = buildStreamParamsConfigSchema;
|
|
311171
311481
|
exports.buildVideoArgs = require_composition.buildVideoArgs;
|
|
311482
|
+
exports.buildViewerLink = buildViewerLink;
|
|
311172
311483
|
exports.builtCapabilityBlockers = builtCapabilityBlockers;
|
|
311173
311484
|
exports.buttonCapability = buttonCapability;
|
|
311174
311485
|
exports.calendarSourceCapability = calendarSourceCapability;
|
|
@@ -311398,6 +311709,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
311398
311709
|
exports.invocationFromEncodeProfile = require_composition.invocationFromEncodeProfile;
|
|
311399
311710
|
exports.isAgentOnlyPlacement = isAgentOnlyPlacement;
|
|
311400
311711
|
exports.isAlarmControllableCap = isAlarmControllableCap;
|
|
311712
|
+
exports.isAppLinkBase = isAppLinkBase;
|
|
311401
311713
|
exports.isArrayOutputSchema = isArrayOutputSchema;
|
|
311402
311714
|
exports.isAudioChunkFormat = require_sleep.isAudioChunkFormat;
|
|
311403
311715
|
exports.isAudioClassName = isAudioClassName;
|
|
@@ -311544,6 +311856,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
311544
311856
|
exports.patchAudio = patchAudio;
|
|
311545
311857
|
exports.petFeederCapability = petFeederCapability;
|
|
311546
311858
|
exports.pickAccessoryControl = pickAccessoryControl;
|
|
311859
|
+
exports.pickAppLinkHub = pickAppLinkHub;
|
|
311547
311860
|
exports.pickClusterStepModels = pickClusterStepModels;
|
|
311548
311861
|
exports.pickClusterStepSettings = pickClusterStepSettings;
|
|
311549
311862
|
exports.pickDetailCropConvention = pickDetailCropConvention;
|
|
@@ -311623,6 +311936,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
311623
311936
|
exports.resolveLocationMode = resolveLocationMode;
|
|
311624
311937
|
exports.resolveMethodAuth = resolveMethodAuth;
|
|
311625
311938
|
exports.resolveModeDelays = resolveModeDelays;
|
|
311939
|
+
exports.resolveModeNotifyPolicy = resolveModeNotifyPolicy;
|
|
311626
311940
|
exports.resolveMutate = resolveMutate;
|
|
311627
311941
|
exports.resolvePoolMemoryPolicy = resolvePoolMemoryPolicy;
|
|
311628
311942
|
exports.resolveRecordingProfiles = resolveRecordingProfiles;
|
|
@@ -311731,6 +312045,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
311731
312045
|
exports.terminalSessionCapability = terminalSessionCapability;
|
|
311732
312046
|
exports.textToHtml = textToHtml;
|
|
311733
312047
|
exports.timeOfDayToMinutes = timeOfDayToMinutes;
|
|
312048
|
+
exports.toAppLinkHubOrigin = toAppLinkHubOrigin;
|
|
311734
312049
|
exports.toDeviceSummary = toDeviceSummary;
|
|
311735
312050
|
exports.toExpressionValue = require_composition.toExpressionValue;
|
|
311736
312051
|
exports.toNodeId = require_sleep.toNodeId;
|
|
@@ -311758,6 +312073,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
311758
312073
|
exports.vectorStoreCapability = vectorStoreCapability;
|
|
311759
312074
|
exports.vibrationCapability = vibrationCapability;
|
|
311760
312075
|
exports.videoclipsCapability = videoclipsCapability;
|
|
312076
|
+
exports.viewerLinkBaseOf = viewerLinkBaseOf;
|
|
311761
312077
|
exports.viewerUiCapability = require_sleep.viewerUiCapability;
|
|
311762
312078
|
exports.waterHeaterCapability = waterHeaterCapability;
|
|
311763
312079
|
exports.weatherCapability = weatherCapability;
|
|
@@ -469412,6 +469728,224 @@ var require_frame_policy = __commonJS({
|
|
|
469412
469728
|
}
|
|
469413
469729
|
});
|
|
469414
469730
|
|
|
469731
|
+
// ../../server/backend/dist/api/cors/cors-policy.js
|
|
469732
|
+
var require_cors_policy = __commonJS({
|
|
469733
|
+
"../../server/backend/dist/api/cors/cors-policy.js"(exports) {
|
|
469734
|
+
"use strict";
|
|
469735
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
469736
|
+
exports.CORS_PREFLIGHT_MAX_AGE_SEC = exports.CORS_EXPOSED_HEADERS = exports.CORS_ALLOWED_HEADERS = exports.CORS_ALLOWED_METHODS = exports.OPAQUE_ORIGIN = exports.VIEWER_PWA_ORIGIN = void 0;
|
|
469737
|
+
exports.normalizeOrigin = normalizeOrigin;
|
|
469738
|
+
exports.parseConfiguredOrigins = parseConfiguredOrigins;
|
|
469739
|
+
exports.builtInOrigins = builtInOrigins;
|
|
469740
|
+
exports.judgeCorsOrigin = judgeCorsOrigin;
|
|
469741
|
+
exports.corsResponseHeaders = corsResponseHeaders;
|
|
469742
|
+
exports.appendVary = appendVary;
|
|
469743
|
+
exports.VIEWER_PWA_ORIGIN = "https://camstack.zentik.app";
|
|
469744
|
+
exports.OPAQUE_ORIGIN = "null";
|
|
469745
|
+
exports.CORS_ALLOWED_METHODS = "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS";
|
|
469746
|
+
exports.CORS_ALLOWED_HEADERS = "authorization, content-type, range, if-range, if-none-match, cache-control, trpc-accept, x-trpc-source, x-trpc-batch-mode";
|
|
469747
|
+
exports.CORS_EXPOSED_HEADERS = "content-range, accept-ranges, content-length, content-disposition, etag, retry-after, x-camstack-reason, x-camstack-reason-code, x-camstack-disposition";
|
|
469748
|
+
exports.CORS_PREFLIGHT_MAX_AGE_SEC = 7200;
|
|
469749
|
+
function normalizeOrigin(raw) {
|
|
469750
|
+
const trimmed = raw.trim();
|
|
469751
|
+
if (trimmed === exports.OPAQUE_ORIGIN)
|
|
469752
|
+
return exports.OPAQUE_ORIGIN;
|
|
469753
|
+
let url;
|
|
469754
|
+
try {
|
|
469755
|
+
url = new URL(trimmed);
|
|
469756
|
+
} catch {
|
|
469757
|
+
return null;
|
|
469758
|
+
}
|
|
469759
|
+
if (url.protocol !== "https:" && url.protocol !== "http:")
|
|
469760
|
+
return null;
|
|
469761
|
+
if (url.username !== "" || url.password !== "")
|
|
469762
|
+
return null;
|
|
469763
|
+
if (url.pathname !== "/" && url.pathname !== "" || url.search !== "" || url.hash !== "") {
|
|
469764
|
+
return null;
|
|
469765
|
+
}
|
|
469766
|
+
return url.origin;
|
|
469767
|
+
}
|
|
469768
|
+
function parseConfiguredOrigins(value) {
|
|
469769
|
+
if (!Array.isArray(value))
|
|
469770
|
+
return { origins: [], rejected: [] };
|
|
469771
|
+
const origins = [];
|
|
469772
|
+
const rejected = [];
|
|
469773
|
+
for (const entry of value) {
|
|
469774
|
+
if (typeof entry !== "string") {
|
|
469775
|
+
rejected.push(String(entry));
|
|
469776
|
+
continue;
|
|
469777
|
+
}
|
|
469778
|
+
const normalized = normalizeOrigin(entry);
|
|
469779
|
+
if (normalized === null)
|
|
469780
|
+
rejected.push(entry);
|
|
469781
|
+
else
|
|
469782
|
+
origins.push(normalized);
|
|
469783
|
+
}
|
|
469784
|
+
return { origins, rejected };
|
|
469785
|
+
}
|
|
469786
|
+
function builtInOrigins(publicOrigin) {
|
|
469787
|
+
const entries = [exports.VIEWER_PWA_ORIGIN, exports.OPAQUE_ORIGIN];
|
|
469788
|
+
const pub = publicOrigin !== void 0 ? normalizeOrigin(publicOrigin) : null;
|
|
469789
|
+
if (pub !== null && pub !== exports.OPAQUE_ORIGIN)
|
|
469790
|
+
entries.push(pub);
|
|
469791
|
+
return entries;
|
|
469792
|
+
}
|
|
469793
|
+
function firstHost(value) {
|
|
469794
|
+
if (value === void 0)
|
|
469795
|
+
return null;
|
|
469796
|
+
const first = value.split(",")[0]?.trim().toLowerCase() ?? "";
|
|
469797
|
+
return first.length > 0 ? first : null;
|
|
469798
|
+
}
|
|
469799
|
+
function hostOfOrigin(origin) {
|
|
469800
|
+
if (origin === exports.OPAQUE_ORIGIN)
|
|
469801
|
+
return null;
|
|
469802
|
+
try {
|
|
469803
|
+
return new URL(origin).host.toLowerCase();
|
|
469804
|
+
} catch {
|
|
469805
|
+
return null;
|
|
469806
|
+
}
|
|
469807
|
+
}
|
|
469808
|
+
function judgeCorsOrigin(facts, listed) {
|
|
469809
|
+
const raw = facts.origin;
|
|
469810
|
+
if (raw === void 0 || raw.length === 0)
|
|
469811
|
+
return { kind: "no-origin" };
|
|
469812
|
+
const normalized = normalizeOrigin(raw);
|
|
469813
|
+
if (normalized === null)
|
|
469814
|
+
return { kind: "denied", origin: raw };
|
|
469815
|
+
if (listed.has(normalized))
|
|
469816
|
+
return { kind: "allowed", origin: raw, reason: "listed" };
|
|
469817
|
+
const originHost = hostOfOrigin(normalized);
|
|
469818
|
+
if (originHost !== null) {
|
|
469819
|
+
const ownHosts = [firstHost(facts.host), firstHost(facts.forwardedHost)];
|
|
469820
|
+
if (ownHosts.includes(originHost))
|
|
469821
|
+
return { kind: "allowed", origin: raw, reason: "own-host" };
|
|
469822
|
+
}
|
|
469823
|
+
return { kind: "denied", origin: raw };
|
|
469824
|
+
}
|
|
469825
|
+
function corsResponseHeaders(origin, preflight) {
|
|
469826
|
+
const base = {
|
|
469827
|
+
"access-control-allow-origin": origin,
|
|
469828
|
+
"access-control-expose-headers": exports.CORS_EXPOSED_HEADERS
|
|
469829
|
+
};
|
|
469830
|
+
if (preflight === null)
|
|
469831
|
+
return base;
|
|
469832
|
+
return {
|
|
469833
|
+
...base,
|
|
469834
|
+
"access-control-allow-methods": exports.CORS_ALLOWED_METHODS,
|
|
469835
|
+
"access-control-allow-headers": exports.CORS_ALLOWED_HEADERS,
|
|
469836
|
+
"access-control-max-age": String(exports.CORS_PREFLIGHT_MAX_AGE_SEC),
|
|
469837
|
+
// A public origin (the PWA) calling a LAN hub is a "private network"
|
|
469838
|
+
// request to Chromium; its preflight must be answered explicitly.
|
|
469839
|
+
...preflight.requestPrivateNetwork ? { "access-control-allow-private-network": "true" } : {}
|
|
469840
|
+
};
|
|
469841
|
+
}
|
|
469842
|
+
function appendVary(existing, token2) {
|
|
469843
|
+
if (existing === void 0 || existing.trim().length === 0)
|
|
469844
|
+
return token2;
|
|
469845
|
+
const parts = existing.split(",").map((p) => p.trim().toLowerCase());
|
|
469846
|
+
if (parts.includes("*") || parts.includes(token2.toLowerCase()))
|
|
469847
|
+
return existing;
|
|
469848
|
+
return `${existing}, ${token2}`;
|
|
469849
|
+
}
|
|
469850
|
+
}
|
|
469851
|
+
});
|
|
469852
|
+
|
|
469853
|
+
// ../../server/backend/dist/api/cors/register-cors-policy.js
|
|
469854
|
+
var require_register_cors_policy = __commonJS({
|
|
469855
|
+
"../../server/backend/dist/api/cors/register-cors-policy.js"(exports) {
|
|
469856
|
+
"use strict";
|
|
469857
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
469858
|
+
exports.createCorsPolicy = createCorsPolicy;
|
|
469859
|
+
exports.registerCorsPolicy = registerCorsPolicy;
|
|
469860
|
+
exports.refuseForeignWsUpgrade = refuseForeignWsUpgrade;
|
|
469861
|
+
var cors_policy_js_1 = require_cors_policy();
|
|
469862
|
+
var MAX_LOGGED_DENIALS = 256;
|
|
469863
|
+
function headerValue(value) {
|
|
469864
|
+
if (Array.isArray(value))
|
|
469865
|
+
return value[0];
|
|
469866
|
+
return value;
|
|
469867
|
+
}
|
|
469868
|
+
function varyText(value) {
|
|
469869
|
+
if (typeof value === "string")
|
|
469870
|
+
return value;
|
|
469871
|
+
if (Array.isArray(value))
|
|
469872
|
+
return value.filter((v) => typeof v === "string").join(", ");
|
|
469873
|
+
return void 0;
|
|
469874
|
+
}
|
|
469875
|
+
function createCorsPolicy(deps) {
|
|
469876
|
+
const builtIns = (0, cors_policy_js_1.builtInOrigins)(deps.publicOrigin);
|
|
469877
|
+
let lastConfigured = /* @__PURE__ */ Symbol("unset");
|
|
469878
|
+
let listed = new Set(builtIns);
|
|
469879
|
+
const loggedDenials = /* @__PURE__ */ new Set();
|
|
469880
|
+
const currentList = () => {
|
|
469881
|
+
const configured = deps.configuredOrigins();
|
|
469882
|
+
if (configured === lastConfigured)
|
|
469883
|
+
return listed;
|
|
469884
|
+
lastConfigured = configured;
|
|
469885
|
+
const parsed = (0, cors_policy_js_1.parseConfiguredOrigins)(configured);
|
|
469886
|
+
if (parsed.rejected.length > 0) {
|
|
469887
|
+
deps.logger.warn("cors: ignored configured origins that are not http(s) origins", {
|
|
469888
|
+
meta: { rejected: parsed.rejected, setting: "server.corsOrigins" }
|
|
469889
|
+
});
|
|
469890
|
+
}
|
|
469891
|
+
listed = /* @__PURE__ */ new Set([...builtIns, ...parsed.origins]);
|
|
469892
|
+
return listed;
|
|
469893
|
+
};
|
|
469894
|
+
return {
|
|
469895
|
+
judge(headers) {
|
|
469896
|
+
const verdict = (0, cors_policy_js_1.judgeCorsOrigin)({
|
|
469897
|
+
origin: headerValue(headers.origin),
|
|
469898
|
+
host: headerValue(headers.host),
|
|
469899
|
+
forwardedHost: headerValue(headers["x-forwarded-host"])
|
|
469900
|
+
}, currentList());
|
|
469901
|
+
if (verdict.kind === "denied" && !loggedDenials.has(verdict.origin)) {
|
|
469902
|
+
if (loggedDenials.size < MAX_LOGGED_DENIALS)
|
|
469903
|
+
loggedDenials.add(verdict.origin);
|
|
469904
|
+
deps.logger.warn("cors: refused a cross-origin caller not on the allowlist", {
|
|
469905
|
+
meta: {
|
|
469906
|
+
origin: verdict.origin,
|
|
469907
|
+
host: headerValue(headers.host) ?? null,
|
|
469908
|
+
hint: "add it to server.corsOrigins (config.yaml) or CAMSTACK_CORS_ORIGINS"
|
|
469909
|
+
}
|
|
469910
|
+
});
|
|
469911
|
+
}
|
|
469912
|
+
return verdict;
|
|
469913
|
+
}
|
|
469914
|
+
};
|
|
469915
|
+
}
|
|
469916
|
+
function registerCorsPolicy(fastify, policy) {
|
|
469917
|
+
fastify.addHook("onRequest", async (request, reply) => {
|
|
469918
|
+
const vary = (0, cors_policy_js_1.appendVary)(varyText(reply.getHeader("vary")), "Origin");
|
|
469919
|
+
reply.header("vary", vary);
|
|
469920
|
+
reply.raw.setHeader("vary", vary);
|
|
469921
|
+
const verdict = policy.judge(request.headers);
|
|
469922
|
+
const isPreflight = request.method === "OPTIONS" && request.headers["access-control-request-method"] !== void 0;
|
|
469923
|
+
if (verdict.kind === "allowed") {
|
|
469924
|
+
const headers = (0, cors_policy_js_1.corsResponseHeaders)(verdict.origin, isPreflight ? {
|
|
469925
|
+
requestPrivateNetwork: headerValue(request.headers["access-control-request-private-network"]) === "true"
|
|
469926
|
+
} : null);
|
|
469927
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
469928
|
+
reply.header(name, value);
|
|
469929
|
+
reply.raw.setHeader(name, value);
|
|
469930
|
+
}
|
|
469931
|
+
}
|
|
469932
|
+
if (request.method === "OPTIONS") {
|
|
469933
|
+
return reply.code(204).send();
|
|
469934
|
+
}
|
|
469935
|
+
return void 0;
|
|
469936
|
+
});
|
|
469937
|
+
}
|
|
469938
|
+
function refuseForeignWsUpgrade(policy, headers, socket) {
|
|
469939
|
+
const verdict = policy.judge(headers);
|
|
469940
|
+
if (verdict.kind !== "denied")
|
|
469941
|
+
return false;
|
|
469942
|
+
socket.write("HTTP/1.1 403 Forbidden\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
|
|
469943
|
+
socket.destroy();
|
|
469944
|
+
return true;
|
|
469945
|
+
}
|
|
469946
|
+
}
|
|
469947
|
+
});
|
|
469948
|
+
|
|
469415
469949
|
// ../../server/backend/dist/boot/integration-id-backfill.js
|
|
469416
469950
|
var require_integration_id_backfill = __commonJS({
|
|
469417
469951
|
"../../server/backend/dist/boot/integration-id-backfill.js"(exports) {
|
|
@@ -485897,16 +486431,6 @@ var require_manual_boot = __commonJS({
|
|
|
485897
486431
|
getHttpAdapter() {
|
|
485898
486432
|
return { getInstance: () => fastify };
|
|
485899
486433
|
},
|
|
485900
|
-
enableCors() {
|
|
485901
|
-
fastify.addHook("onRequest", async (request, reply) => {
|
|
485902
|
-
reply.header("access-control-allow-origin", "*");
|
|
485903
|
-
reply.header("access-control-allow-methods", "GET,POST,PUT,DELETE,OPTIONS,PATCH");
|
|
485904
|
-
reply.header("access-control-allow-headers", "content-type,authorization");
|
|
485905
|
-
if (request.method === "OPTIONS") {
|
|
485906
|
-
reply.status(204).send();
|
|
485907
|
-
}
|
|
485908
|
-
});
|
|
485909
|
-
},
|
|
485910
486434
|
enableShutdownHooks() {
|
|
485911
486435
|
if (shutdownHooksRegistered)
|
|
485912
486436
|
return;
|
|
@@ -486017,6 +486541,7 @@ var require_main4 = __commonJS({
|
|
|
486017
486541
|
var spa_static_1 = require_spa_static();
|
|
486018
486542
|
var spa_mount_1 = require_spa_mount();
|
|
486019
486543
|
var frame_policy_1 = require_frame_policy();
|
|
486544
|
+
var register_cors_policy_1 = require_register_cors_policy();
|
|
486020
486545
|
var cap_providers_1 = require_cap_providers();
|
|
486021
486546
|
var logging_settings_1 = require_logging_settings();
|
|
486022
486547
|
var request_census_settings_1 = require_request_census_settings();
|
|
@@ -486183,8 +486708,14 @@ var require_main4 = __commonJS({
|
|
|
486183
486708
|
const fastifyOpts = tlsOptions ? { https: tlsOptions } : {};
|
|
486184
486709
|
const app = await (0, manual_boot_1.bootManual)({ infra, fastifyOpts });
|
|
486185
486710
|
app.enableShutdownHooks();
|
|
486186
|
-
app.enableCors();
|
|
486187
486711
|
const fastify = app.getHttpAdapter().getInstance();
|
|
486712
|
+
const corsConfig = app.get(config_service_1.ConfigService);
|
|
486713
|
+
const corsPolicy = (0, register_cors_policy_1.createCorsPolicy)({
|
|
486714
|
+
configuredOrigins: () => corsConfig.get("server.corsOrigins"),
|
|
486715
|
+
publicOrigin: process.env.CAMSTACK_PUBLIC_ORIGIN,
|
|
486716
|
+
logger: app.get(logging_service_1.LoggingService).createLogger("cors")
|
|
486717
|
+
});
|
|
486718
|
+
(0, register_cors_policy_1.registerCorsPolicy)(fastify, corsPolicy);
|
|
486188
486719
|
await fastify.register(cookie_1.default);
|
|
486189
486720
|
(0, frame_policy_1.registerFramePolicy)(fastify);
|
|
486190
486721
|
fastify.addHook("onRequest", async (request) => {
|
|
@@ -486767,6 +487298,8 @@ var require_main4 = __commonJS({
|
|
|
486767
487298
|
httpServer.on("upgrade", (request, socket, head) => {
|
|
486768
487299
|
const pathname = (request.url ?? "").split("?")[0];
|
|
486769
487300
|
if (pathname === "/trpc") {
|
|
487301
|
+
if ((0, register_cors_policy_1.refuseForeignWsUpgrade)(corsPolicy, request.headers, socket))
|
|
487302
|
+
return;
|
|
486770
487303
|
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
486771
487304
|
wss.emit("connection", ws, request);
|
|
486772
487305
|
});
|