@camstack/addon-auth 1.2.171 → 1.2.172
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/CHANGELOG.md +6 -0
- package/dist/{dist-CAPIgbvM.mjs → dist-Dvcuof5S.mjs} +901 -115
- package/dist/{dist-BCzztoSM.js → dist-xyaDmv1T.js} +901 -115
- package/dist/oidc/auth-oidc.addon.js +76 -130
- package/dist/oidc/auth-oidc.addon.mjs +76 -130
- package/dist/webauthn/_stub.js +1 -1
- package/dist/webauthn/{_virtual_mf-localSharedImportMap___mfe_internal__addon_auth_webauthn_widgets-cmM4lkBD.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_auth_webauthn_widgets-U5-CdChb.mjs} +2 -2
- package/dist/webauthn/_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CQJ6wKXR.mjs +26 -0
- package/dist/webauthn/auth-webauthn.addon.js +1 -1
- package/dist/webauthn/auth-webauthn.addon.mjs +1 -1
- package/dist/webauthn/{hostInit-hRFE010M.mjs → hostInit-D-l58LQN.mjs} +2 -2
- package/dist/webauthn/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/webauthn/_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Di6YsQxe.mjs +0 -26
|
@@ -5587,7 +5587,7 @@ var ZodIssueCode = {
|
|
|
5587
5587
|
var ZodFirstPartyTypeKind;
|
|
5588
5588
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5589
5589
|
//#endregion
|
|
5590
|
-
//#region ../types/dist/sleep-
|
|
5590
|
+
//#region ../types/dist/sleep-CeyhrcOk.mjs
|
|
5591
5591
|
/**
|
|
5592
5592
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5593
5593
|
* window to float samples (D455).
|
|
@@ -7654,6 +7654,7 @@ var BaseAddon = class {
|
|
|
7654
7654
|
* a warning and falls back rather than crashing boot.
|
|
7655
7655
|
*/
|
|
7656
7656
|
state(key, schema, fallback) {
|
|
7657
|
+
this._declaredStateKeys.add(key);
|
|
7657
7658
|
return createDurableState({
|
|
7658
7659
|
key,
|
|
7659
7660
|
schema,
|
|
@@ -7669,6 +7670,96 @@ var BaseAddon = class {
|
|
|
7669
7670
|
} })
|
|
7670
7671
|
});
|
|
7671
7672
|
}
|
|
7673
|
+
/** Durable-state keys this process registered through {@link state}. */
|
|
7674
|
+
_declaredStateKeys = /* @__PURE__ */ new Set();
|
|
7675
|
+
/**
|
|
7676
|
+
* Stale-data audit: every global-settings key this addon still declares —
|
|
7677
|
+
* constructor defaults, settings-schema fields (layout containers included),
|
|
7678
|
+
* durable-state keys and the root of each `secretStatePaths` entry. Answered
|
|
7679
|
+
* here, in the addon's own process, so the hub keeps no copy of it.
|
|
7680
|
+
*/
|
|
7681
|
+
async getDeclaredSettingsKeys() {
|
|
7682
|
+
return { keys: [...this.declaredKeySet()].toSorted() };
|
|
7683
|
+
}
|
|
7684
|
+
declaredKeySet() {
|
|
7685
|
+
const keys = new Set(Object.keys(this.defaults));
|
|
7686
|
+
const schema = this.globalSettingsSchema();
|
|
7687
|
+
if (schema) for (const section of schema.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
7688
|
+
for (const key of this._declaredStateKeys) keys.add(key);
|
|
7689
|
+
for (const path of this.secretStatePaths) {
|
|
7690
|
+
const root = path.split(/[.[]/, 1)[0];
|
|
7691
|
+
if (root) keys.add(root);
|
|
7692
|
+
}
|
|
7693
|
+
return keys;
|
|
7694
|
+
}
|
|
7695
|
+
/**
|
|
7696
|
+
* Stale-data audit: remove stored global-settings keys the addon no longer
|
|
7697
|
+
* declares, and clear the keychain values their markers held — except a value
|
|
7698
|
+
* a surviving key still points at. A declared or absent key is refused.
|
|
7699
|
+
*/
|
|
7700
|
+
async unsetStoredSettingsKeys(keys) {
|
|
7701
|
+
const settings = this._ctx?.settings;
|
|
7702
|
+
const raw = this.rawSettings();
|
|
7703
|
+
if (!settings || !raw) return {
|
|
7704
|
+
removed: [],
|
|
7705
|
+
refused: keys.map((key) => ({
|
|
7706
|
+
key,
|
|
7707
|
+
reason: "no settings store"
|
|
7708
|
+
})),
|
|
7709
|
+
secretsCleared: 0
|
|
7710
|
+
};
|
|
7711
|
+
let stored;
|
|
7712
|
+
try {
|
|
7713
|
+
stored = await raw.readAddonStore();
|
|
7714
|
+
} catch (error) {
|
|
7715
|
+
const reason = `store unreadable: ${error instanceof Error ? error.message : "unknown"}`;
|
|
7716
|
+
return {
|
|
7717
|
+
removed: [],
|
|
7718
|
+
refused: keys.map((key) => ({
|
|
7719
|
+
key,
|
|
7720
|
+
reason
|
|
7721
|
+
})),
|
|
7722
|
+
secretsCleared: 0
|
|
7723
|
+
};
|
|
7724
|
+
}
|
|
7725
|
+
const declared = this.declaredKeySet();
|
|
7726
|
+
const removed = [];
|
|
7727
|
+
const refused = [];
|
|
7728
|
+
for (const key of keys) {
|
|
7729
|
+
const base = key.split("@", 1)[0] ?? key;
|
|
7730
|
+
if (declared.has(base)) refused.push({
|
|
7731
|
+
key,
|
|
7732
|
+
reason: "still declared by the addon"
|
|
7733
|
+
});
|
|
7734
|
+
else if (!(key in stored)) refused.push({
|
|
7735
|
+
key,
|
|
7736
|
+
reason: "not stored"
|
|
7737
|
+
});
|
|
7738
|
+
else removed.push(key);
|
|
7739
|
+
}
|
|
7740
|
+
if (removed.length === 0) return {
|
|
7741
|
+
removed,
|
|
7742
|
+
refused,
|
|
7743
|
+
secretsCleared: 0
|
|
7744
|
+
};
|
|
7745
|
+
const kept = /* @__PURE__ */ new Set();
|
|
7746
|
+
const held = /* @__PURE__ */ new Set();
|
|
7747
|
+
for (const [key, value] of Object.entries(stored)) {
|
|
7748
|
+
const target = removed.includes(key) ? held : kept;
|
|
7749
|
+
for (const ref of collectSecretMarkerRefs(value)) target.add(ref);
|
|
7750
|
+
}
|
|
7751
|
+
const refsToClear = [...held].filter((ref) => !kept.has(ref));
|
|
7752
|
+
const patch = {};
|
|
7753
|
+
for (const key of removed) patch[key] = void 0;
|
|
7754
|
+
await settings.writeAddonStore(patch);
|
|
7755
|
+
const secretsCleared = refsToClear.length > 0 && this._ctx?.secrets ? await this._ctx.secrets.delete(refsToClear) : 0;
|
|
7756
|
+
await this.resolveConfig();
|
|
7757
|
+
return {
|
|
7758
|
+
removed,
|
|
7759
|
+
refused,
|
|
7760
|
+
secretsCleared
|
|
7761
|
+
};
|
|
7762
|
+
}
|
|
7672
7763
|
/** Per-device variant of {@link state}, backed by the per-device store. */
|
|
7673
7764
|
deviceState(deviceId, key, schema, fallback) {
|
|
7674
7765
|
return createDurableState({
|
|
@@ -7939,6 +8030,21 @@ function dropPerNodeFields(fields) {
|
|
|
7939
8030
|
}
|
|
7940
8031
|
return kept;
|
|
7941
8032
|
}
|
|
8033
|
+
function collectFieldKeys(fields) {
|
|
8034
|
+
const collected = [];
|
|
8035
|
+
for (const field of fields) {
|
|
8036
|
+
if (field.type === "group") {
|
|
8037
|
+
collected.push(...collectFieldKeys(field.fields));
|
|
8038
|
+
continue;
|
|
8039
|
+
}
|
|
8040
|
+
if (field.type === "sub-tabs") {
|
|
8041
|
+
for (const tab of field.tabs) collected.push(...collectFieldKeys(tab.fields));
|
|
8042
|
+
continue;
|
|
8043
|
+
}
|
|
8044
|
+
if ("key" in field && typeof field.key === "string") collected.push(field.key);
|
|
8045
|
+
}
|
|
8046
|
+
return collected;
|
|
8047
|
+
}
|
|
7942
8048
|
function collectPerNodeFieldKeys(fields) {
|
|
7943
8049
|
const collected = [];
|
|
7944
8050
|
for (const field of fields) {
|
|
@@ -16623,8 +16729,172 @@ object({
|
|
|
16623
16729
|
quantity: ReadingQuantitySchema,
|
|
16624
16730
|
unit: string().min(1)
|
|
16625
16731
|
});
|
|
16626
|
-
|
|
16627
|
-
|
|
16732
|
+
new Set([
|
|
16733
|
+
{
|
|
16734
|
+
id: "person",
|
|
16735
|
+
name: "Person"
|
|
16736
|
+
},
|
|
16737
|
+
{
|
|
16738
|
+
id: "vehicle",
|
|
16739
|
+
name: "Vehicle"
|
|
16740
|
+
},
|
|
16741
|
+
{
|
|
16742
|
+
id: "animal",
|
|
16743
|
+
name: "Animal"
|
|
16744
|
+
},
|
|
16745
|
+
{
|
|
16746
|
+
id: "package",
|
|
16747
|
+
name: "Package"
|
|
16748
|
+
}
|
|
16749
|
+
].map((l) => l.id));
|
|
16750
|
+
var COCO_TO_MACRO = {
|
|
16751
|
+
mapping: {
|
|
16752
|
+
person: "person",
|
|
16753
|
+
bicycle: "vehicle",
|
|
16754
|
+
car: "vehicle",
|
|
16755
|
+
motorcycle: "vehicle",
|
|
16756
|
+
airplane: "vehicle",
|
|
16757
|
+
bus: "vehicle",
|
|
16758
|
+
train: "vehicle",
|
|
16759
|
+
truck: "vehicle",
|
|
16760
|
+
boat: "vehicle",
|
|
16761
|
+
bird: "animal",
|
|
16762
|
+
cat: "animal",
|
|
16763
|
+
dog: "animal",
|
|
16764
|
+
horse: "animal",
|
|
16765
|
+
sheep: "animal",
|
|
16766
|
+
cow: "animal",
|
|
16767
|
+
elephant: "animal",
|
|
16768
|
+
bear: "animal",
|
|
16769
|
+
zebra: "animal",
|
|
16770
|
+
giraffe: "animal",
|
|
16771
|
+
suitcase: "package",
|
|
16772
|
+
backpack: "package",
|
|
16773
|
+
handbag: "package"
|
|
16774
|
+
},
|
|
16775
|
+
preserveOriginal: false
|
|
16776
|
+
};
|
|
16777
|
+
/**
|
|
16778
|
+
* WHAT a detection-shaped leaf is about: one MACRO class (person, vehicle,
|
|
16779
|
+
* animal, package) plus an OPTIONAL label that narrows it.
|
|
16780
|
+
*
|
|
16781
|
+
* The taxonomy is `COCO_TO_MACRO` (and `CLASS_MAP_MACRO_TARGETS`) — never a
|
|
16782
|
+
* second list. The label that fits depends on the macro class:
|
|
16783
|
+
*
|
|
16784
|
+
* - `animal` → a sub-class (`dog`, `cat`, …);
|
|
16785
|
+
* - `person` → a known face (an identity of the `face-gallery`);
|
|
16786
|
+
* - `vehicle` → a plate (its text) or a sub-class (`car`, `truck`, …);
|
|
16787
|
+
* - `package` → a sub-class.
|
|
16788
|
+
*
|
|
16789
|
+
* `other` exists only so a class the taxonomy does not know (a custom model's
|
|
16790
|
+
* `forklift`) survives the conversion of a stored recipe without widening.
|
|
16791
|
+
*
|
|
16792
|
+
* A label is decided LATE (D683): face recognition and LPR land after the
|
|
16793
|
+
* detection starts. The track-lifecycle `update` event carries the newly
|
|
16794
|
+
* resolved `label` / `plateText`, which is why a leaf with a label fires when
|
|
16795
|
+
* the subject GETS it — not at the first detection.
|
|
16796
|
+
*/
|
|
16797
|
+
var SubClassLabelSchema = object({
|
|
16798
|
+
kind: literal("sub-class"),
|
|
16799
|
+
className: string().min(1)
|
|
16800
|
+
});
|
|
16801
|
+
var IdentityLabelSchema = object({
|
|
16802
|
+
kind: literal("identity"),
|
|
16803
|
+
/** The `face-gallery` identity id (stable across a rename). */
|
|
16804
|
+
identityId: string().min(1),
|
|
16805
|
+
/** The identity's name — what a track-lifecycle event carries as `label`. */
|
|
16806
|
+
name: string().min(1)
|
|
16807
|
+
});
|
|
16808
|
+
var PlateLabelSchema = object({
|
|
16809
|
+
kind: literal("plate"),
|
|
16810
|
+
text: string().min(1)
|
|
16811
|
+
});
|
|
16812
|
+
function macroOf$1(className) {
|
|
16813
|
+
return COCO_TO_MACRO.mapping[className.toLowerCase()] ?? className.toLowerCase();
|
|
16814
|
+
}
|
|
16815
|
+
/** A sub-class label must belong to the macro it is under. */
|
|
16816
|
+
function subClassBelongs(macro, label) {
|
|
16817
|
+
return label === void 0 || macroOf$1(label.className) === macro;
|
|
16818
|
+
}
|
|
16819
|
+
var subClassOf = (macro) => SubClassLabelSchema.refine((l) => subClassBelongs(macro, l), { message: `that class is not a kind of ${macro} in the detection taxonomy` });
|
|
16820
|
+
var DetectionSubjectSchema = discriminatedUnion("macro", [
|
|
16821
|
+
object({
|
|
16822
|
+
macro: literal("animal"),
|
|
16823
|
+
label: subClassOf("animal").optional()
|
|
16824
|
+
}),
|
|
16825
|
+
object({
|
|
16826
|
+
macro: literal("person"),
|
|
16827
|
+
label: IdentityLabelSchema.optional()
|
|
16828
|
+
}),
|
|
16829
|
+
object({
|
|
16830
|
+
macro: literal("vehicle"),
|
|
16831
|
+
label: discriminatedUnion("kind", [SubClassLabelSchema.refine((l) => subClassBelongs("vehicle", l), { message: "that class is not a kind of vehicle in the detection taxonomy" }), PlateLabelSchema]).optional()
|
|
16832
|
+
}),
|
|
16833
|
+
object({
|
|
16834
|
+
macro: literal("package"),
|
|
16835
|
+
label: subClassOf("package").optional()
|
|
16836
|
+
}),
|
|
16837
|
+
object({
|
|
16838
|
+
macro: literal("other"),
|
|
16839
|
+
className: string().min(1)
|
|
16840
|
+
})
|
|
16841
|
+
]);
|
|
16842
|
+
/**
|
|
16843
|
+
* The subject of a PARKED object. The stationary registry's event carries a
|
|
16844
|
+
* class and a zone, no face and no plate — an identity or plate label there
|
|
16845
|
+
* could never match, so the schema refuses it instead of letting it sit dead.
|
|
16846
|
+
*/
|
|
16847
|
+
var StationarySubjectSchema = DetectionSubjectSchema.refine((s) => s.macro === "other" || s.label === void 0 || s.label.kind === "sub-class", { message: "a parked object carries no face or plate — only a class can narrow it" });
|
|
16848
|
+
/**
|
|
16849
|
+
* A stored class string as a subject: a macro name stays a macro; a raw class
|
|
16850
|
+
* the taxonomy files under a macro becomes that macro plus the sub-class label
|
|
16851
|
+
* (`dog` → animal / dog); anything else is `other`, kept verbatim.
|
|
16852
|
+
*/
|
|
16853
|
+
function subjectFromClassName(className) {
|
|
16854
|
+
const name = className.trim().toLowerCase();
|
|
16855
|
+
const macro = COCO_TO_MACRO.mapping[name];
|
|
16856
|
+
if (new Set(Object.values(COCO_TO_MACRO.mapping)).has(name)) return macroOnly(name);
|
|
16857
|
+
if (macro === void 0) return {
|
|
16858
|
+
macro: "other",
|
|
16859
|
+
className
|
|
16860
|
+
};
|
|
16861
|
+
const label = {
|
|
16862
|
+
kind: "sub-class",
|
|
16863
|
+
className: name
|
|
16864
|
+
};
|
|
16865
|
+
switch (macro) {
|
|
16866
|
+
case "animal": return {
|
|
16867
|
+
macro: "animal",
|
|
16868
|
+
label
|
|
16869
|
+
};
|
|
16870
|
+
case "vehicle": return {
|
|
16871
|
+
macro: "vehicle",
|
|
16872
|
+
label
|
|
16873
|
+
};
|
|
16874
|
+
case "package": return {
|
|
16875
|
+
macro: "package",
|
|
16876
|
+
label
|
|
16877
|
+
};
|
|
16878
|
+
default: return {
|
|
16879
|
+
macro: "other",
|
|
16880
|
+
className
|
|
16881
|
+
};
|
|
16882
|
+
}
|
|
16883
|
+
}
|
|
16884
|
+
function macroOnly(macro) {
|
|
16885
|
+
switch (macro) {
|
|
16886
|
+
case "animal": return { macro: "animal" };
|
|
16887
|
+
case "person": return { macro: "person" };
|
|
16888
|
+
case "vehicle": return { macro: "vehicle" };
|
|
16889
|
+
case "package": return { macro: "package" };
|
|
16890
|
+
default: return {
|
|
16891
|
+
macro: "other",
|
|
16892
|
+
className: macro
|
|
16893
|
+
};
|
|
16894
|
+
}
|
|
16895
|
+
}
|
|
16896
|
+
/** How a state leaf compares a device field to a value. Derived from the
|
|
16897
|
+
* field's `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
|
|
16628
16898
|
var AutomationConditionOperatorSchema = _enum([
|
|
16629
16899
|
"eq",
|
|
16630
16900
|
"ne",
|
|
@@ -16635,12 +16905,76 @@ var AutomationConditionOperatorSchema = _enum([
|
|
|
16635
16905
|
"contains",
|
|
16636
16906
|
"in"
|
|
16637
16907
|
]);
|
|
16638
|
-
|
|
16639
|
-
|
|
16908
|
+
/**
|
|
16909
|
+
* D8 compliance, and it is the reason a "becomes" leaf is not merely an event
|
|
16910
|
+
* subscription: it evaluates against the **state mirror**, which is reconciled,
|
|
16911
|
+
* and an event only WAKES the evaluation. A dropped event therefore DELAYS a
|
|
16912
|
+
* fire; it does not lose it.
|
|
16913
|
+
*/
|
|
16914
|
+
var DeviceBecomesLeafSchema = object({
|
|
16915
|
+
kind: literal("device-becomes"),
|
|
16916
|
+
deviceId: number().int().nonnegative(),
|
|
16917
|
+
cap: string().min(1),
|
|
16918
|
+
fieldPath: string().min(1),
|
|
16919
|
+
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
16920
|
+
becomes: union([
|
|
16921
|
+
string(),
|
|
16922
|
+
number(),
|
|
16923
|
+
boolean()
|
|
16924
|
+
]).optional(),
|
|
16925
|
+
/** Only on a CHANGE of value, not on every re-report. */
|
|
16926
|
+
edge: boolean().optional(),
|
|
16927
|
+
/** The new value must hold this long before it counts. */
|
|
16928
|
+
forMs: number().int().min(0).max(864e5).optional(),
|
|
16929
|
+
/** Collapse a burst into one occurrence. */
|
|
16930
|
+
debounceMs: number().int().min(0).max(6e5).optional()
|
|
16931
|
+
});
|
|
16932
|
+
var DeviceEventLeafSchema = object({
|
|
16933
|
+
kind: literal("device-event"),
|
|
16934
|
+
/** An `EventCategory` value. */
|
|
16935
|
+
category: string().min(1),
|
|
16936
|
+
deviceId: number().int().nonnegative().optional()
|
|
16937
|
+
});
|
|
16938
|
+
var ScheduleLeafSchema = object({
|
|
16939
|
+
kind: literal("schedule"),
|
|
16940
|
+
cron: string().min(1).max(120)
|
|
16941
|
+
});
|
|
16942
|
+
var ManualLeafSchema = object({ kind: literal("manual") });
|
|
16943
|
+
var IntervalLeafSchema = object({
|
|
16944
|
+
kind: literal("interval"),
|
|
16945
|
+
minutes: number().int().min(1).max(1440)
|
|
16946
|
+
});
|
|
16947
|
+
var DetectionLeafSchema = object({
|
|
16948
|
+
kind: literal("detection"),
|
|
16949
|
+
/** One macro class each, optionally narrowed by a label; a track of any listed subject fires. */
|
|
16950
|
+
subjects: array(DetectionSubjectSchema).min(1),
|
|
16951
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16952
|
+
/** The track must have visited at least one of these zones. */
|
|
16953
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
16954
|
+
/** Best-so-far confidence the track must reach. */
|
|
16955
|
+
minScore: number().min(0).max(1).optional()
|
|
16956
|
+
});
|
|
16957
|
+
var StationaryLeafSchema = object({
|
|
16958
|
+
kind: literal("stationary"),
|
|
16959
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16960
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
16961
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
16962
|
+
/** `appeared`: it became parked. `departed`: the registry retired it. */
|
|
16963
|
+
phase: _enum(["appeared", "departed"])
|
|
16964
|
+
});
|
|
16965
|
+
/** "is": one device field compared to one value, NOW. */
|
|
16966
|
+
var DeviceIsLeafSchema = object({
|
|
16967
|
+
kind: literal("device-is"),
|
|
16640
16968
|
deviceId: number().int().nonnegative(),
|
|
16641
16969
|
cap: string().min(1),
|
|
16642
16970
|
fieldPath: string().min(1),
|
|
16643
16971
|
operator: AutomationConditionOperatorSchema,
|
|
16972
|
+
/**
|
|
16973
|
+
* The value. A number on a quantity field is stored in the field's base unit
|
|
16974
|
+
* (D944); a quantity value is the WRITE form, which the save boundary
|
|
16975
|
+
* replaces with the converted number and `unit`. A leaf that still carries
|
|
16976
|
+
* one is never evaluated (it fails).
|
|
16977
|
+
*/
|
|
16644
16978
|
value: union([
|
|
16645
16979
|
string(),
|
|
16646
16980
|
number(),
|
|
@@ -16648,24 +16982,26 @@ var AutomationConditionLeafSchema = object({
|
|
|
16648
16982
|
array(union([string(), number()])),
|
|
16649
16983
|
QuantityValueSchema
|
|
16650
16984
|
]),
|
|
16985
|
+
/** The unit the person picked for `value` (display only; `value` is in the base unit). */
|
|
16651
16986
|
unit: string().min(1).optional()
|
|
16652
16987
|
});
|
|
16653
|
-
|
|
16988
|
+
/**
|
|
16989
|
+
* True when the camera currently has a PARKED object matching `subjects` in at
|
|
16990
|
+
* least one of `zones`. Reads the zone-analytics snapshot through the same
|
|
16991
|
+
* mirror as every other state leaf, so a dropped event never decides it (D49).
|
|
16992
|
+
*/
|
|
16993
|
+
var StationaryPresentLeafSchema = object({
|
|
16654
16994
|
kind: literal("stationary-present"),
|
|
16655
16995
|
deviceId: number().int().nonnegative(),
|
|
16656
|
-
|
|
16657
|
-
classes: array(string().min(1)).min(1).optional(),
|
|
16658
|
-
/** The parked object must be in at least one of these zones. */
|
|
16996
|
+
subjects: array(StationarySubjectSchema).min(1).optional(),
|
|
16659
16997
|
zones: array(string().min(1)).min(1).optional()
|
|
16660
16998
|
});
|
|
16661
16999
|
/**
|
|
16662
|
-
* The
|
|
16663
|
-
*
|
|
16664
|
-
*
|
|
16665
|
-
* validation is the SAME function `ExpressionSourceSchema` runs, so the two
|
|
16666
|
-
* cannot drift — an expression that one accepts, the other accepts.
|
|
17000
|
+
* The escape hatch: the bounded expression engine over named device bindings.
|
|
17001
|
+
* Declared as a plain object so a discriminated union can read `kind`; the
|
|
17002
|
+
* author-time validation is the SAME function `ExpressionSourceSchema` runs.
|
|
16667
17003
|
*/
|
|
16668
|
-
var
|
|
17004
|
+
var ExpressionLeafSchema = object({
|
|
16669
17005
|
kind: literal("expression"),
|
|
16670
17006
|
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
16671
17007
|
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
@@ -16677,55 +17013,62 @@ var AutomationConditionExpressionSchema = object({
|
|
|
16677
17013
|
path: ["expr"]
|
|
16678
17014
|
});
|
|
16679
17015
|
});
|
|
16680
|
-
var
|
|
17016
|
+
var AutomationWhenSchema = lazy(() => discriminatedUnion("kind", [
|
|
16681
17017
|
object({
|
|
16682
17018
|
kind: literal("all"),
|
|
16683
|
-
children: array(
|
|
17019
|
+
children: array(AutomationWhenSchema)
|
|
16684
17020
|
}),
|
|
16685
17021
|
object({
|
|
16686
17022
|
kind: literal("any"),
|
|
16687
|
-
children: array(
|
|
17023
|
+
children: array(AutomationWhenSchema)
|
|
16688
17024
|
}),
|
|
16689
17025
|
object({
|
|
16690
17026
|
kind: literal("not"),
|
|
16691
|
-
child:
|
|
17027
|
+
child: AutomationWhenSchema
|
|
16692
17028
|
}),
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
17029
|
+
DeviceBecomesLeafSchema,
|
|
17030
|
+
DeviceEventLeafSchema,
|
|
17031
|
+
ScheduleLeafSchema,
|
|
17032
|
+
ManualLeafSchema,
|
|
17033
|
+
IntervalLeafSchema,
|
|
17034
|
+
DetectionLeafSchema,
|
|
17035
|
+
StationaryLeafSchema,
|
|
17036
|
+
DeviceIsLeafSchema,
|
|
17037
|
+
StationaryPresentLeafSchema,
|
|
17038
|
+
ExpressionLeafSchema
|
|
16696
17039
|
]));
|
|
16697
17040
|
/**
|
|
16698
|
-
*
|
|
16699
|
-
*
|
|
16700
|
-
*
|
|
16701
|
-
*
|
|
16702
|
-
*
|
|
16703
|
-
*
|
|
16704
|
-
*
|
|
16705
|
-
*
|
|
16706
|
-
|
|
16707
|
-
|
|
17041
|
+
* The recipe shape before the single `when` tree: a flat list of triggers
|
|
17042
|
+
* (OR'd, each an instant) and an optional condition tree. Stored recipes —
|
|
17043
|
+
* the `AUTOMATION_RECIPE` literal of every block saved so far, and whatever an
|
|
17044
|
+
* older client still posts — are in this shape, so it stays READABLE here, and
|
|
17045
|
+
* {@link convertLegacyRecipe} turns it into the new one, losslessly and one
|
|
17046
|
+
* way. Nothing writes this shape any more.
|
|
17047
|
+
*
|
|
17048
|
+
* `{ triggers: [t1…tn], conditions?: C }`
|
|
17049
|
+
* → `when = all(any(t1…tn), C)`, or `any(t1…tn)` without `C`;
|
|
17050
|
+
* a single trigger is not wrapped in `any`.
|
|
17051
|
+
* a `condition` leaf → a `device-is` leaf (the "is" verb);
|
|
17052
|
+
* a `device-state` trigger → a `device-becomes` leaf (the "becomes" verb);
|
|
17053
|
+
* `classes: ['dog']` → the macro `animal` with the label `dog`.
|
|
17054
|
+
*/
|
|
17055
|
+
var LegacyTriggerSchema = discriminatedUnion("kind", [
|
|
16708
17056
|
object({
|
|
16709
17057
|
kind: literal("device-state"),
|
|
16710
17058
|
deviceId: number().int().nonnegative(),
|
|
16711
17059
|
cap: string().min(1),
|
|
16712
17060
|
fieldPath: string().min(1),
|
|
16713
|
-
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
16714
17061
|
becomes: union([
|
|
16715
17062
|
string(),
|
|
16716
17063
|
number(),
|
|
16717
17064
|
boolean()
|
|
16718
17065
|
]).optional(),
|
|
16719
|
-
/** Only on a CHANGE of value, not on every re-report. */
|
|
16720
17066
|
edge: boolean().optional(),
|
|
16721
|
-
/** The condition must hold this long before the run starts. */
|
|
16722
17067
|
forMs: number().int().min(0).max(864e5).optional(),
|
|
16723
|
-
/** Collapse a burst into one run. */
|
|
16724
17068
|
debounceMs: number().int().min(0).max(6e5).optional()
|
|
16725
17069
|
}),
|
|
16726
17070
|
object({
|
|
16727
17071
|
kind: literal("device-event"),
|
|
16728
|
-
/** An `EventCategory` value. */
|
|
16729
17072
|
category: string().min(1),
|
|
16730
17073
|
deviceId: number().int().nonnegative().optional()
|
|
16731
17074
|
}),
|
|
@@ -16736,25 +17079,16 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
16736
17079
|
object({ kind: literal("manual") }),
|
|
16737
17080
|
object({
|
|
16738
17081
|
kind: literal("detection"),
|
|
16739
|
-
/** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
|
|
16740
|
-
* matches every raw class that maps to it; any other name matches
|
|
16741
|
-
* exactly. */
|
|
16742
17082
|
classes: array(string().min(1)).min(1),
|
|
16743
17083
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16744
|
-
/** The track must have visited at least one of these zones. */
|
|
16745
17084
|
zones: array(string().min(1)).min(1).optional(),
|
|
16746
|
-
/** Best-so-far confidence the track must reach. */
|
|
16747
17085
|
minScore: number().min(0).max(1).optional()
|
|
16748
17086
|
}),
|
|
16749
17087
|
object({
|
|
16750
17088
|
kind: literal("stationary"),
|
|
16751
17089
|
deviceIds: array(number().int().nonnegative()).min(1),
|
|
16752
|
-
/** Class names; a macro class matches like the detection trigger. */
|
|
16753
17090
|
classes: array(string().min(1)).min(1).optional(),
|
|
16754
|
-
/** The parked object must be in at least one of these zones. */
|
|
16755
17091
|
zones: array(string().min(1)).min(1).optional(),
|
|
16756
|
-
/** `appeared`: it became parked. `departed`: the registry retired it.
|
|
16757
|
-
* The vocabulary of `PipelineAnalyticsStationaryChanged`. */
|
|
16758
17092
|
phase: _enum(["appeared", "departed"])
|
|
16759
17093
|
}),
|
|
16760
17094
|
object({
|
|
@@ -16762,6 +17096,143 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
16762
17096
|
minutes: number().int().min(1).max(1440)
|
|
16763
17097
|
})
|
|
16764
17098
|
]);
|
|
17099
|
+
var LegacyConditionLeafSchema = object({
|
|
17100
|
+
kind: literal("condition"),
|
|
17101
|
+
deviceId: number().int().nonnegative(),
|
|
17102
|
+
cap: string().min(1),
|
|
17103
|
+
fieldPath: string().min(1),
|
|
17104
|
+
operator: AutomationConditionOperatorSchema,
|
|
17105
|
+
value: union([
|
|
17106
|
+
string(),
|
|
17107
|
+
number(),
|
|
17108
|
+
boolean(),
|
|
17109
|
+
array(union([string(), number()])),
|
|
17110
|
+
QuantityValueSchema
|
|
17111
|
+
]),
|
|
17112
|
+
unit: string().min(1).optional()
|
|
17113
|
+
});
|
|
17114
|
+
var LegacyStationaryPresentSchema = object({
|
|
17115
|
+
kind: literal("stationary-present"),
|
|
17116
|
+
deviceId: number().int().nonnegative(),
|
|
17117
|
+
classes: array(string().min(1)).min(1).optional(),
|
|
17118
|
+
zones: array(string().min(1)).min(1).optional()
|
|
17119
|
+
});
|
|
17120
|
+
var LegacyExpressionSchema = object({
|
|
17121
|
+
kind: literal("expression"),
|
|
17122
|
+
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
17123
|
+
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
17124
|
+
}).superRefine((src, ctx) => {
|
|
17125
|
+
const err = validateExpressionSource(src);
|
|
17126
|
+
if (err !== null) ctx.addIssue({
|
|
17127
|
+
code: "custom",
|
|
17128
|
+
message: err,
|
|
17129
|
+
path: ["expr"]
|
|
17130
|
+
});
|
|
17131
|
+
});
|
|
17132
|
+
var LegacyConditionSchema = lazy(() => discriminatedUnion("kind", [
|
|
17133
|
+
object({
|
|
17134
|
+
kind: literal("all"),
|
|
17135
|
+
children: array(LegacyConditionSchema)
|
|
17136
|
+
}),
|
|
17137
|
+
object({
|
|
17138
|
+
kind: literal("any"),
|
|
17139
|
+
children: array(LegacyConditionSchema)
|
|
17140
|
+
}),
|
|
17141
|
+
object({
|
|
17142
|
+
kind: literal("not"),
|
|
17143
|
+
child: LegacyConditionSchema
|
|
17144
|
+
}),
|
|
17145
|
+
LegacyConditionLeafSchema,
|
|
17146
|
+
LegacyExpressionSchema,
|
|
17147
|
+
LegacyStationaryPresentSchema
|
|
17148
|
+
]));
|
|
17149
|
+
function convertTrigger(trigger) {
|
|
17150
|
+
switch (trigger.kind) {
|
|
17151
|
+
case "device-state": return {
|
|
17152
|
+
...trigger,
|
|
17153
|
+
kind: "device-becomes"
|
|
17154
|
+
};
|
|
17155
|
+
case "detection": {
|
|
17156
|
+
const { classes, ...rest } = trigger;
|
|
17157
|
+
return {
|
|
17158
|
+
...rest,
|
|
17159
|
+
subjects: classes.map(subjectFromClassName)
|
|
17160
|
+
};
|
|
17161
|
+
}
|
|
17162
|
+
case "stationary": {
|
|
17163
|
+
const { classes, ...rest } = trigger;
|
|
17164
|
+
return {
|
|
17165
|
+
...rest,
|
|
17166
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
17167
|
+
};
|
|
17168
|
+
}
|
|
17169
|
+
default: return trigger;
|
|
17170
|
+
}
|
|
17171
|
+
}
|
|
17172
|
+
/** An old condition tree as a `when` subtree: `condition` → "is", classes → subjects. */
|
|
17173
|
+
function convertLegacyCondition(condition) {
|
|
17174
|
+
switch (condition.kind) {
|
|
17175
|
+
case "condition": return {
|
|
17176
|
+
...condition,
|
|
17177
|
+
kind: "device-is"
|
|
17178
|
+
};
|
|
17179
|
+
case "stationary-present": {
|
|
17180
|
+
const { classes, ...rest } = condition;
|
|
17181
|
+
return {
|
|
17182
|
+
...rest,
|
|
17183
|
+
...classes === void 0 ? {} : { subjects: classes.map(subjectFromClassName) }
|
|
17184
|
+
};
|
|
17185
|
+
}
|
|
17186
|
+
case "expression": return condition;
|
|
17187
|
+
case "not": return {
|
|
17188
|
+
kind: "not",
|
|
17189
|
+
child: convertLegacyCondition(condition.child)
|
|
17190
|
+
};
|
|
17191
|
+
case "all":
|
|
17192
|
+
case "any": return {
|
|
17193
|
+
kind: condition.kind,
|
|
17194
|
+
children: condition.children.map(convertLegacyCondition)
|
|
17195
|
+
};
|
|
17196
|
+
}
|
|
17197
|
+
}
|
|
17198
|
+
/** `all(any(t1…tn), C)`, or `any(t1…tn)`; a single trigger is not wrapped in `any`. */
|
|
17199
|
+
function convertLegacyWhen(half) {
|
|
17200
|
+
const leaves = half.triggers.map(convertTrigger);
|
|
17201
|
+
const first = leaves[0];
|
|
17202
|
+
const triggers = leaves.length === 1 && first !== void 0 ? first : {
|
|
17203
|
+
kind: "any",
|
|
17204
|
+
children: leaves
|
|
17205
|
+
};
|
|
17206
|
+
if (half.conditions === void 0) return triggers;
|
|
17207
|
+
return {
|
|
17208
|
+
kind: "all",
|
|
17209
|
+
children: [triggers, convertLegacyCondition(half.conditions)]
|
|
17210
|
+
};
|
|
17211
|
+
}
|
|
17212
|
+
/**
|
|
17213
|
+
* The automation RECIPE — what a visually-authored automation is, before it
|
|
17214
|
+
* becomes code.
|
|
17215
|
+
*
|
|
17216
|
+
* This is the data half of `docs/design/2026-08-08-automation-scripts-custom-devices.md`
|
|
17217
|
+
* Phase 6. A recipe is not an engine and never evaluates anything: it is a
|
|
17218
|
+
* declarative description that {@link generateAutomationBlock} compiles to the
|
|
17219
|
+
* TypeScript of an ordinary core block. There is therefore no second rule
|
|
17220
|
+
* engine, no second store and no second runtime — the block runner is the
|
|
17221
|
+
* runtime, `core_blocks` is the store (§2.1).
|
|
17222
|
+
*
|
|
17223
|
+
* Two parts:
|
|
17224
|
+
*
|
|
17225
|
+
* - **`when`** — ONE tree (`./when.ts`) of all/any/not over event leaves
|
|
17226
|
+
* (instants) and state leaves (durations). It replaces the flat trigger list
|
|
17227
|
+
* plus the separate condition tree; the firing rule is in that file and in
|
|
17228
|
+
* ADR "one tree".
|
|
17229
|
+
* - **Actions** — `NcRuleActionSchema`'s two steps, plus the `{kind:'code'}`
|
|
17230
|
+
* fragment of §3.2.2. See {@link AutomationActionSchema} for the ONE place
|
|
17231
|
+
* this had to diverge from "verbatim", and why.
|
|
17232
|
+
*
|
|
17233
|
+
* A recipe stored in the old shape (`triggers` + `conditions`) still LOADS:
|
|
17234
|
+
* {@link AutomationRecipeSchema} (the parse-anywhere schema) converts it on parse. Nothing writes it.
|
|
17235
|
+
*/
|
|
16765
17236
|
/**
|
|
16766
17237
|
* One action step.
|
|
16767
17238
|
*
|
|
@@ -16864,69 +17335,49 @@ var AutomationRunModeSchema = discriminatedUnion("mode", [
|
|
|
16864
17335
|
minutes: number().int().min(1).max(1440)
|
|
16865
17336
|
})
|
|
16866
17337
|
]);
|
|
16867
|
-
var
|
|
16868
|
-
|
|
16869
|
-
conditions: AutomationConditionSchema.optional(),
|
|
17338
|
+
var CurrentAutomationRecipeSchema = object({
|
|
17339
|
+
when: AutomationWhenSchema,
|
|
16870
17340
|
actions: array(AutomationActionSchema),
|
|
16871
17341
|
runMode: AutomationRunModeSchema.optional(),
|
|
16872
17342
|
/** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
|
|
16873
17343
|
keepTraces: number().int().min(1).max(100).optional()
|
|
16874
17344
|
});
|
|
16875
|
-
|
|
16876
|
-
|
|
16877
|
-
|
|
16878
|
-
|
|
16879
|
-
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16892
|
-
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16897
|
-
|
|
16898
|
-
|
|
16899
|
-
|
|
16900
|
-
bus: "vehicle",
|
|
16901
|
-
train: "vehicle",
|
|
16902
|
-
truck: "vehicle",
|
|
16903
|
-
boat: "vehicle",
|
|
16904
|
-
bird: "animal",
|
|
16905
|
-
cat: "animal",
|
|
16906
|
-
dog: "animal",
|
|
16907
|
-
horse: "animal",
|
|
16908
|
-
sheep: "animal",
|
|
16909
|
-
cow: "animal",
|
|
16910
|
-
elephant: "animal",
|
|
16911
|
-
bear: "animal",
|
|
16912
|
-
zebra: "animal",
|
|
16913
|
-
giraffe: "animal",
|
|
16914
|
-
suitcase: "package",
|
|
16915
|
-
backpack: "package",
|
|
16916
|
-
handbag: "package"
|
|
16917
|
-
},
|
|
16918
|
-
preserveOriginal: false
|
|
16919
|
-
};
|
|
17345
|
+
/** A recipe as it was stored before the single tree. Read-only: nothing writes this. */
|
|
17346
|
+
var LegacyAutomationRecipeSchema = object({
|
|
17347
|
+
triggers: array(LegacyTriggerSchema),
|
|
17348
|
+
conditions: LegacyConditionSchema.optional(),
|
|
17349
|
+
actions: array(AutomationActionSchema),
|
|
17350
|
+
runMode: AutomationRunModeSchema.optional(),
|
|
17351
|
+
keepTraces: number().int().min(1).max(100).optional()
|
|
17352
|
+
});
|
|
17353
|
+
/** The old shape as the new one, lossless. */
|
|
17354
|
+
function convertLegacyRecipe(legacy) {
|
|
17355
|
+
const { triggers, conditions, ...rest } = legacy;
|
|
17356
|
+
return {
|
|
17357
|
+
when: convertLegacyWhen({
|
|
17358
|
+
triggers,
|
|
17359
|
+
conditions
|
|
17360
|
+
}),
|
|
17361
|
+
...rest
|
|
17362
|
+
};
|
|
17363
|
+
}
|
|
17364
|
+
/**
|
|
17365
|
+
* Where recipes are PARSED (the core-blocks cap, the MCP tool, the literal a
|
|
17366
|
+
* saved block carries): the new shape as it is, or the old shape converted to
|
|
17367
|
+
* it. The output type is always the new one.
|
|
17368
|
+
*/
|
|
17369
|
+
var AutomationRecipeSchema = union([CurrentAutomationRecipeSchema, LegacyAutomationRecipeSchema.transform(convertLegacyRecipe)]);
|
|
16920
17370
|
new Set(Object.values(COCO_TO_MACRO.mapping));
|
|
16921
17371
|
/**
|
|
16922
17372
|
* Run traces — what an automation (or, later, an Action run) DID, node by node,
|
|
16923
17373
|
* so the editor can paint every block green or red with its reason.
|
|
16924
17374
|
*
|
|
16925
|
-
* A trace is data, not a log: it covers the WHOLE tree — the
|
|
16926
|
-
* every
|
|
16927
|
-
* short-circuit never reached), the run-mode verdict and every action
|
|
16928
|
-
* each addressed by a stable path (`
|
|
16929
|
-
* for an Action run).
|
|
17375
|
+
* A trace is data, not a log: it covers the WHOLE tree — the event leaf that
|
|
17376
|
+
* fired, every node of the `when` tree (containers and leaves, including the
|
|
17377
|
+
* ones a short-circuit never reached), the run-mode verdict and every action
|
|
17378
|
+
* step — each addressed by a stable path (`when.0.1`, `actions.2`, or `steps.N`
|
|
17379
|
+
* for an Action run). Traces written before the single tree carry
|
|
17380
|
+
* `conditions.*` paths and still parse. Skipped
|
|
16930
17381
|
* evaluations are traced too, and identical consecutive skips collapse into a
|
|
16931
17382
|
* repeat count so a trigger that fails every 5 minutes cannot flush real runs.
|
|
16932
17383
|
*
|
|
@@ -16958,6 +17409,8 @@ var TraceNodeOutcomeSchema = _enum([
|
|
|
16958
17409
|
]);
|
|
16959
17410
|
var AutomationTriggerTraceSchema = object({
|
|
16960
17411
|
kind: string().min(1),
|
|
17412
|
+
/** The event leaf that fired (`when`, `when.0.1`); absent on traces written before the single tree. */
|
|
17413
|
+
path: string().min(1).optional(),
|
|
16961
17414
|
outcome: _enum(["pass", "fail"]),
|
|
16962
17415
|
/** Why an event was rejected ("class person not in [dog]") or what fired. */
|
|
16963
17416
|
reason: string(),
|
|
@@ -16965,15 +17418,23 @@ var AutomationTriggerTraceSchema = object({
|
|
|
16965
17418
|
vars: record(string(), TraceValueSchema)
|
|
16966
17419
|
});
|
|
16967
17420
|
var AutomationConditionTraceNodeSchema = object({
|
|
16968
|
-
/** `
|
|
17421
|
+
/** `when` for the root, `when.<i>` for its i-th child, … (`conditions…` on an old trace). */
|
|
16969
17422
|
path: string().min(1),
|
|
16970
17423
|
kind: _enum([
|
|
16971
17424
|
"all",
|
|
16972
17425
|
"any",
|
|
16973
17426
|
"not",
|
|
16974
17427
|
"condition",
|
|
17428
|
+
"device-is",
|
|
16975
17429
|
"expression",
|
|
16976
|
-
"stationary-present"
|
|
17430
|
+
"stationary-present",
|
|
17431
|
+
"device-becomes",
|
|
17432
|
+
"device-event",
|
|
17433
|
+
"schedule",
|
|
17434
|
+
"interval",
|
|
17435
|
+
"manual",
|
|
17436
|
+
"detection",
|
|
17437
|
+
"stationary"
|
|
16977
17438
|
]),
|
|
16978
17439
|
outcome: TraceNodeOutcomeSchema,
|
|
16979
17440
|
reason: string(),
|
|
@@ -17007,6 +17468,12 @@ var AutomationStepTraceSchema = object({
|
|
|
17007
17468
|
deviceId: number().int().optional(),
|
|
17008
17469
|
startedAt: number().optional(),
|
|
17009
17470
|
endedAt: number().optional(),
|
|
17471
|
+
/**
|
|
17472
|
+
* The parameters the step SENT, after `{{vars.x}}` substitution — what the
|
|
17473
|
+
* device was actually asked. Bounded like trigger `vars`; a secret parameter
|
|
17474
|
+
* is shown as {@link REDACTED_ARG}. Absent on traces written before it existed.
|
|
17475
|
+
*/
|
|
17476
|
+
args: record(string(), TraceValueSchema).optional(),
|
|
17010
17477
|
outcome: _enum([
|
|
17011
17478
|
"ok",
|
|
17012
17479
|
"error",
|
|
@@ -17775,6 +18242,23 @@ method(object({
|
|
|
17775
18242
|
addonId: string(),
|
|
17776
18243
|
nodeId: string().optional()
|
|
17777
18244
|
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
18245
|
+
addonId: string(),
|
|
18246
|
+
nodeId: string().optional()
|
|
18247
|
+
}), object({ keys: array(string()) }).nullable(), { auth: "admin" }), method(object({
|
|
18248
|
+
addonId: string(),
|
|
18249
|
+
nodeId: string().optional(),
|
|
18250
|
+
keys: array(string())
|
|
18251
|
+
}), object({
|
|
18252
|
+
removed: array(string()),
|
|
18253
|
+
refused: array(object({
|
|
18254
|
+
key: string(),
|
|
18255
|
+
reason: string()
|
|
18256
|
+
})),
|
|
18257
|
+
secretsCleared: number()
|
|
18258
|
+
}), {
|
|
18259
|
+
kind: "mutation",
|
|
18260
|
+
auth: "admin"
|
|
18261
|
+
}), method(object({
|
|
17778
18262
|
addonId: string(),
|
|
17779
18263
|
deviceId: number(),
|
|
17780
18264
|
nodeId: string().optional()
|
|
@@ -21730,6 +22214,8 @@ var StorageKindSchema = object({
|
|
|
21730
22214
|
"orphaned",
|
|
21731
22215
|
"dropped"
|
|
21732
22216
|
]),
|
|
22217
|
+
/** An owner declared this kind since the engine started. */
|
|
22218
|
+
declaredThisBoot: boolean(),
|
|
21733
22219
|
/** `null` when the caller asked for no counts (`counts: false`). */
|
|
21734
22220
|
rows: number().int().nonnegative().nullable(),
|
|
21735
22221
|
/** Rows x the average size of a sample; null for an empty kind. */
|
|
@@ -21741,6 +22227,51 @@ var StorageKindSchema = object({
|
|
|
21741
22227
|
/** The whole declaration, secret paths and entry descriptor included (the entries service builds its handle from it). */
|
|
21742
22228
|
declaration: RecordKindDeclarationSchema
|
|
21743
22229
|
});
|
|
22230
|
+
_enum([
|
|
22231
|
+
"orphaned",
|
|
22232
|
+
"stale",
|
|
22233
|
+
"unknown"
|
|
22234
|
+
]);
|
|
22235
|
+
/** A record kind nobody declared since its owner started, or whose owner is gone. */
|
|
22236
|
+
var StaleKindFindingSchema = object({
|
|
22237
|
+
owner: string(),
|
|
22238
|
+
kind: string(),
|
|
22239
|
+
/** `unknown`: the owner could not be judged (not running, or its state unreadable) - never dropped. */
|
|
22240
|
+
verdict: _enum(["orphaned", "unknown"]),
|
|
22241
|
+
reason: string(),
|
|
22242
|
+
rows: number().int().nonnegative().nullable(),
|
|
22243
|
+
/** local-auth's tables are never dropped by this audit. */
|
|
22244
|
+
protected: boolean()
|
|
22245
|
+
});
|
|
22246
|
+
/** A stored global-settings key the running addon no longer declares. */
|
|
22247
|
+
var StaleSettingsKeyFindingSchema = object({
|
|
22248
|
+
addonId: string(),
|
|
22249
|
+
/** The stored key as written, a per-node `<key>@<nodeId>` suffix included. */
|
|
22250
|
+
key: string(),
|
|
22251
|
+
/**
|
|
22252
|
+
* Keychain refs whose ONLY marker sits under this key: in use by stale data,
|
|
22253
|
+
* not orphans yet. Removing the key releases them.
|
|
22254
|
+
*/
|
|
22255
|
+
secretRefs: array(string())
|
|
22256
|
+
});
|
|
22257
|
+
/** An addon the audit could not judge, with the reason. Never reported as stale. */
|
|
22258
|
+
var StaleUnknownSchema = object({
|
|
22259
|
+
subject: string(),
|
|
22260
|
+
reason: string()
|
|
22261
|
+
});
|
|
22262
|
+
var StaleDataReportSchema = object({
|
|
22263
|
+
/** Epoch ms of the last finished scan; `null` before the first. */
|
|
22264
|
+
scannedAt: number().nullable(),
|
|
22265
|
+
scanning: boolean(),
|
|
22266
|
+
trigger: _enum([
|
|
22267
|
+
"boot",
|
|
22268
|
+
"interval",
|
|
22269
|
+
"manual"
|
|
22270
|
+
]).nullable(),
|
|
22271
|
+
kinds: array(StaleKindFindingSchema),
|
|
22272
|
+
settingsKeys: array(StaleSettingsKeyFindingSchema),
|
|
22273
|
+
unknown: array(StaleUnknownSchema)
|
|
22274
|
+
});
|
|
21744
22275
|
method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
|
|
21745
22276
|
owner: string().min(1).optional(),
|
|
21746
22277
|
/** `false` skips the per-kind row count (a catalog read only). Default true. */
|
|
@@ -21748,7 +22279,30 @@ method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: arr
|
|
|
21748
22279
|
}), object({ kinds: array(StorageKindSchema) }), { auth: "admin" }), method(RecordQueryInputSchema.extend({
|
|
21749
22280
|
owner: string().min(1),
|
|
21750
22281
|
kind: RecordKindNameSchema
|
|
21751
|
-
}), RecordQueryResultSchema, { auth: "admin" })
|
|
22282
|
+
}), RecordQueryResultSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, { auth: "admin" }), method(object({}), StaleDataReportSchema, {
|
|
22283
|
+
kind: "mutation",
|
|
22284
|
+
auth: "admin"
|
|
22285
|
+
}), method(object({
|
|
22286
|
+
owner: string().min(1),
|
|
22287
|
+
kind: RecordKindNameSchema
|
|
22288
|
+
}), object({
|
|
22289
|
+
deleted: number().int().nonnegative(),
|
|
22290
|
+
secretsReleased: number().int().nonnegative()
|
|
22291
|
+
}), {
|
|
22292
|
+
kind: "mutation",
|
|
22293
|
+
auth: "admin",
|
|
22294
|
+
caller: "required"
|
|
22295
|
+
}), method(object({
|
|
22296
|
+
addonId: string().min(1),
|
|
22297
|
+
key: string().min(1)
|
|
22298
|
+
}), object({
|
|
22299
|
+
removed: boolean(),
|
|
22300
|
+
secretsCleared: number().int().nonnegative()
|
|
22301
|
+
}), {
|
|
22302
|
+
kind: "mutation",
|
|
22303
|
+
auth: "admin",
|
|
22304
|
+
caller: "required"
|
|
22305
|
+
});
|
|
21752
22306
|
/**
|
|
21753
22307
|
* record-entries - the ONE admin surface for every list of user-created entries
|
|
21754
22308
|
* (D881): notification targets, brokers, LLM profiles, anything an addon
|
|
@@ -21887,6 +22441,12 @@ method(object({
|
|
|
21887
22441
|
}), method(object({ deviceId: number().int() }), object({ refs: array(string()).readonly() }), {
|
|
21888
22442
|
kind: "mutation",
|
|
21889
22443
|
auth: "admin"
|
|
22444
|
+
}), method(object({
|
|
22445
|
+
refs: RefListSchema,
|
|
22446
|
+
onBehalfOf: string().min(1)
|
|
22447
|
+
}), object({ released: number().int() }), {
|
|
22448
|
+
kind: "mutation",
|
|
22449
|
+
auth: "admin"
|
|
21890
22450
|
}), method(object({}), array(KeychainSecretMetaSchema).readonly(), { auth: "admin" }), method(object({}), KeychainStateSchema, { auth: "admin" });
|
|
21891
22451
|
/**
|
|
21892
22452
|
* device-history — the ONE mechanism for numeric history (D850).
|
|
@@ -22676,7 +23236,9 @@ var DiscoveredChildDeviceSchema = lazy(() => object({
|
|
|
22676
23236
|
/** Upstream-system identity + rendering hints for the candidate. */
|
|
22677
23237
|
sourceInfo: SourceInfoSchema.optional(),
|
|
22678
23238
|
/** Nested entity-children for accordion preview — integrations populate, Hubs omit. */
|
|
22679
|
-
children: array(DiscoveredChildDeviceSchema).readonly().optional()
|
|
23239
|
+
children: array(DiscoveredChildDeviceSchema).readonly().optional(),
|
|
23240
|
+
/** `childNativeId` of the gateway candidate in the same list this device sits behind. */
|
|
23241
|
+
parentStableId: string().optional()
|
|
22680
23242
|
}));
|
|
22681
23243
|
/**
|
|
22682
23244
|
* Status block — populated by the integration after each
|
|
@@ -43009,6 +43571,79 @@ object({
|
|
|
43009
43571
|
metadata: record(string(), unknown()).optional()
|
|
43010
43572
|
});
|
|
43011
43573
|
/**
|
|
43574
|
+
* HOW a provider can be found on the network. The provider only DECLARES the
|
|
43575
|
+
* mode; the `local-network` scan engine runs it once for every provider that
|
|
43576
|
+
* asked (one multicast browse, one host sweep) and hands the raw hits back to
|
|
43577
|
+
* `classifyDiscoveryHits`. A provider never opens a discovery socket itself,
|
|
43578
|
+
* except through a `custom` mode.
|
|
43579
|
+
*/
|
|
43580
|
+
var DiscoveryModeSchema = discriminatedUnion("kind", [
|
|
43581
|
+
object({
|
|
43582
|
+
kind: literal("mdns"),
|
|
43583
|
+
/** DNS-SD service type, e.g. `_esphomelib._tcp`. */
|
|
43584
|
+
serviceType: string().min(1),
|
|
43585
|
+
/** Regular expression an instance name must match (case-insensitive). */
|
|
43586
|
+
instancePattern: string().optional()
|
|
43587
|
+
}),
|
|
43588
|
+
object({
|
|
43589
|
+
kind: literal("ws-discovery"),
|
|
43590
|
+
/** Probe types (e.g. `dn:NetworkVideoTransmitter`); omitted = any device. */
|
|
43591
|
+
types: array(string()).optional()
|
|
43592
|
+
}),
|
|
43593
|
+
object({
|
|
43594
|
+
kind: literal("ssdp"),
|
|
43595
|
+
searchTarget: string().min(1)
|
|
43596
|
+
}),
|
|
43597
|
+
object({
|
|
43598
|
+
kind: literal("udp-broadcast"),
|
|
43599
|
+
port: number().int().min(1).max(65535),
|
|
43600
|
+
payloadHex: string().regex(/^([0-9a-fA-F]{2})*$/),
|
|
43601
|
+
/** Port replies arrive on, when the device answers somewhere other than the source port. */
|
|
43602
|
+
listenPort: number().int().min(1).max(65535).optional()
|
|
43603
|
+
}),
|
|
43604
|
+
object({
|
|
43605
|
+
kind: literal("http-probe"),
|
|
43606
|
+
port: number().int().min(1).max(65535),
|
|
43607
|
+
path: string().startsWith("/"),
|
|
43608
|
+
method: _enum(["GET", "POST"]).default("GET"),
|
|
43609
|
+
bodyText: string().optional(),
|
|
43610
|
+
contentType: string().optional(),
|
|
43611
|
+
tls: boolean().default(false),
|
|
43612
|
+
/** Status codes that count as a hit. Omitted = any HTTP answer. */
|
|
43613
|
+
acceptStatus: array(number().int()).optional()
|
|
43614
|
+
}),
|
|
43615
|
+
object({
|
|
43616
|
+
kind: literal("custom"),
|
|
43617
|
+
/** Why the engine cannot do it (an allowlisted exception, e.g. a vendor UDP protocol). */
|
|
43618
|
+
reason: string().min(1)
|
|
43619
|
+
})
|
|
43620
|
+
]);
|
|
43621
|
+
/** What the engine saw on the wire for ONE declared mode; the provider classifies it. */
|
|
43622
|
+
var DiscoveryHitSchema = object({
|
|
43623
|
+
/** Index into the provider's own `getDiscoveryModes()` array. */
|
|
43624
|
+
modeIndex: number().int().min(0),
|
|
43625
|
+
host: string(),
|
|
43626
|
+
port: number().int(),
|
|
43627
|
+
http: object({
|
|
43628
|
+
status: number().int(),
|
|
43629
|
+
headers: record(string(), string()),
|
|
43630
|
+
/** At most 16 KiB. */
|
|
43631
|
+
bodyText: string()
|
|
43632
|
+
}).optional(),
|
|
43633
|
+
mdns: object({
|
|
43634
|
+
instance: string(),
|
|
43635
|
+
host: string(),
|
|
43636
|
+
port: number().int(),
|
|
43637
|
+
txt: record(string(), string())
|
|
43638
|
+
}).optional(),
|
|
43639
|
+
udp: object({ payloadHex: string() }).optional(),
|
|
43640
|
+
wsd: object({
|
|
43641
|
+
xaddrs: array(string()),
|
|
43642
|
+
types: array(string()),
|
|
43643
|
+
scopes: array(string())
|
|
43644
|
+
}).optional()
|
|
43645
|
+
});
|
|
43646
|
+
/**
|
|
43012
43647
|
* Candidate handed back from discovery and accepted by
|
|
43013
43648
|
* `adoptDiscoveredDevice`. Shape mirrors the in-process
|
|
43014
43649
|
* `DiscoveredDevice` interface used by `DeviceDiscovery`.
|
|
@@ -43043,7 +43678,17 @@ var DiscoveryCandidateSchema = object({
|
|
|
43043
43678
|
/** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
|
|
43044
43679
|
onboardedDeviceId: number().optional(),
|
|
43045
43680
|
/** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
|
|
43046
|
-
onboardedName: string().optional()
|
|
43681
|
+
onboardedName: string().optional(),
|
|
43682
|
+
/**
|
|
43683
|
+
* This candidate is an INTEGRATION to set up (a gateway, a hub, a controller),
|
|
43684
|
+
* not a device to adopt. Replaces the `prefilledConfig.setupIntegration` marker,
|
|
43685
|
+
* which is still read for one release.
|
|
43686
|
+
*/
|
|
43687
|
+
setupIntegration: boolean().optional(),
|
|
43688
|
+
/** `stableId` of the gateway candidate this device was found BEHIND. */
|
|
43689
|
+
parentStableId: string().optional(),
|
|
43690
|
+
/** `false` = shown for context but not pickable. Default true. */
|
|
43691
|
+
selectable: boolean().optional()
|
|
43047
43692
|
});
|
|
43048
43693
|
/**
|
|
43049
43694
|
* Flat device summary returned by `createDevice` / `adoptDiscoveredDevice`.
|
|
@@ -43096,6 +43741,12 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
|
|
|
43096
43741
|
}), method(object({}), boolean()), method(object({ params: record(string(), unknown()).optional() }), array(DiscoveryCandidateSchema), {
|
|
43097
43742
|
kind: "mutation",
|
|
43098
43743
|
auth: "admin"
|
|
43744
|
+
}), method(object({}), array(DiscoveryModeSchema)), method(object({
|
|
43745
|
+
hits: array(DiscoveryHitSchema),
|
|
43746
|
+
params: record(string(), unknown()).optional()
|
|
43747
|
+
}), array(DiscoveryCandidateSchema), {
|
|
43748
|
+
kind: "mutation",
|
|
43749
|
+
auth: "admin"
|
|
43099
43750
|
}), method(object({}), CreationSchemaOutputSchema), method(object({}), object({ deviceType: _enum(DeviceType).nullable() })), method(object({ candidate: DiscoveryCandidateSchema }), DeviceSummarySchema, {
|
|
43100
43751
|
kind: "mutation",
|
|
43101
43752
|
auth: "admin"
|
|
@@ -43823,17 +44474,23 @@ method(object({
|
|
|
43823
44474
|
}), method(object({}), object({ providers: array(object({
|
|
43824
44475
|
addonId: string(),
|
|
43825
44476
|
label: string()
|
|
43826
|
-
})).readonly() }), { auth: "admin" }), method(
|
|
43827
|
-
|
|
43828
|
-
|
|
43829
|
-
|
|
43830
|
-
|
|
43831
|
-
|
|
43832
|
-
|
|
43833
|
-
|
|
43834
|
-
}),
|
|
44477
|
+
})).readonly() }), { auth: "admin" }), method(
|
|
44478
|
+
/** `subnets`: extra CIDRs for THIS scan, on top of the hub's own and the saved list. */
|
|
44479
|
+
object({ subnets: array(string()).optional() }),
|
|
44480
|
+
object({ groups: array(object({
|
|
44481
|
+
addonId: string(),
|
|
44482
|
+
label: string(),
|
|
44483
|
+
candidates: array(DiscoveryCandidateSchema).readonly(),
|
|
44484
|
+
error: string().nullable()
|
|
44485
|
+
})).readonly() }),
|
|
44486
|
+
{
|
|
44487
|
+
kind: "mutation",
|
|
44488
|
+
auth: "admin"
|
|
44489
|
+
}
|
|
44490
|
+
), method(object({
|
|
43835
44491
|
addonId: string(),
|
|
43836
|
-
params: record(string(), unknown()).optional()
|
|
44492
|
+
params: record(string(), unknown()).optional(),
|
|
44493
|
+
subnets: array(string()).optional()
|
|
43837
44494
|
}), object({ candidates: array(DiscoveryCandidateSchema).readonly() }), {
|
|
43838
44495
|
kind: "mutation",
|
|
43839
44496
|
auth: "admin"
|
|
@@ -61512,7 +62169,9 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
61512
62169
|
id: string(),
|
|
61513
62170
|
settings: record(string(), unknown()),
|
|
61514
62171
|
/** Keys the form's schema declares secret (by type) — keychain-stored (D787). */
|
|
61515
|
-
secretKeys: array(string()).optional()
|
|
62172
|
+
secretKeys: array(string()).optional(),
|
|
62173
|
+
/** The integration's own addon applies the change in-process and asks the hub not to respawn it. */
|
|
62174
|
+
skipRestart: boolean().optional()
|
|
61516
62175
|
}), object({ success: boolean() }), {
|
|
61517
62176
|
kind: "mutation",
|
|
61518
62177
|
auth: "admin"
|
|
@@ -61989,6 +62648,39 @@ var TlsStatusSchema = object({
|
|
|
61989
62648
|
hasCa: boolean()
|
|
61990
62649
|
}).nullable()
|
|
61991
62650
|
});
|
|
62651
|
+
/** One provider's ask of the scan engine: the modes it declared. */
|
|
62652
|
+
var ScanRequestSchema = object({
|
|
62653
|
+
providerId: string().min(1),
|
|
62654
|
+
modes: array(DiscoveryModeSchema)
|
|
62655
|
+
});
|
|
62656
|
+
var ScanErrorSchema = object({
|
|
62657
|
+
/** Absent for a failure that is the scan's own (a bad subnet, a socket that would not open). */
|
|
62658
|
+
providerId: string().optional(),
|
|
62659
|
+
/** The mode family that failed (`mdns`, `http-probe`, …). */
|
|
62660
|
+
mode: string().optional(),
|
|
62661
|
+
message: string()
|
|
62662
|
+
});
|
|
62663
|
+
/** What one scan did, per mode family; the engine logs the same numbers once. */
|
|
62664
|
+
var ScanStatsSchema = object({
|
|
62665
|
+
hostsProbed: number().int(),
|
|
62666
|
+
hits: number().int(),
|
|
62667
|
+
timeouts: number().int(),
|
|
62668
|
+
byMode: record(string(), object({
|
|
62669
|
+
probed: number().int(),
|
|
62670
|
+
hits: number().int(),
|
|
62671
|
+
timeouts: number().int()
|
|
62672
|
+
}))
|
|
62673
|
+
});
|
|
62674
|
+
var ScanNetworkResultSchema = object({
|
|
62675
|
+
hits: array(object({
|
|
62676
|
+
providerId: string(),
|
|
62677
|
+
hit: DiscoveryHitSchema
|
|
62678
|
+
})),
|
|
62679
|
+
/** CIDRs actually covered: the hub's own /24s, the saved list and the per-call list. */
|
|
62680
|
+
subnetsScanned: array(string()),
|
|
62681
|
+
errors: array(ScanErrorSchema),
|
|
62682
|
+
stats: ScanStatsSchema
|
|
62683
|
+
});
|
|
61992
62684
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
61993
62685
|
/**
|
|
61994
62686
|
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
@@ -62043,6 +62735,16 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
62043
62735
|
}), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
|
|
62044
62736
|
kind: "mutation",
|
|
62045
62737
|
auth: "admin"
|
|
62738
|
+
}), method(object({
|
|
62739
|
+
requests: array(ScanRequestSchema),
|
|
62740
|
+
subnets: array(string()).optional()
|
|
62741
|
+
}), ScanNetworkResultSchema, {
|
|
62742
|
+
kind: "mutation",
|
|
62743
|
+
auth: "admin",
|
|
62744
|
+
timeoutMs: 9e4
|
|
62745
|
+
}), method(_void(), object({ subnets: array(string()) }), { auth: "admin" }), method(object({ subnets: array(string()) }), object({ subnets: array(string()) }), {
|
|
62746
|
+
kind: "mutation",
|
|
62747
|
+
auth: "admin"
|
|
62046
62748
|
}), method(_void(), TlsStatusSchema, {
|
|
62047
62749
|
kind: "mutation",
|
|
62048
62750
|
auth: "admin"
|
|
@@ -68884,6 +69586,13 @@ Object.freeze({
|
|
|
68884
69586
|
access: "create",
|
|
68885
69587
|
role: "admin"
|
|
68886
69588
|
},
|
|
69589
|
+
"addonSettings.getDeclaredSettingsKeys": {
|
|
69590
|
+
capName: "addon-settings",
|
|
69591
|
+
capScope: "system",
|
|
69592
|
+
addonId: null,
|
|
69593
|
+
access: "view",
|
|
69594
|
+
role: "admin"
|
|
69595
|
+
},
|
|
68887
69596
|
"addonSettings.getDeviceSettings": {
|
|
68888
69597
|
capName: "addon-settings",
|
|
68889
69598
|
capScope: "system",
|
|
@@ -68905,6 +69614,13 @@ Object.freeze({
|
|
|
68905
69614
|
access: "view",
|
|
68906
69615
|
role: "admin"
|
|
68907
69616
|
},
|
|
69617
|
+
"addonSettings.unsetStoredSettingsKeys": {
|
|
69618
|
+
capName: "addon-settings",
|
|
69619
|
+
capScope: "system",
|
|
69620
|
+
addonId: null,
|
|
69621
|
+
access: "create",
|
|
69622
|
+
role: "admin"
|
|
69623
|
+
},
|
|
68908
69624
|
"addonSettings.updateDeviceSettings": {
|
|
68909
69625
|
capName: "addon-settings",
|
|
68910
69626
|
capScope: "system",
|
|
@@ -71320,6 +72036,13 @@ Object.freeze({
|
|
|
71320
72036
|
access: "create",
|
|
71321
72037
|
role: "admin"
|
|
71322
72038
|
},
|
|
72039
|
+
"deviceProvider.classifyDiscoveryHits": {
|
|
72040
|
+
capName: "device-provider",
|
|
72041
|
+
capScope: "system",
|
|
72042
|
+
addonId: null,
|
|
72043
|
+
access: "create",
|
|
72044
|
+
role: "admin"
|
|
72045
|
+
},
|
|
71323
72046
|
"deviceProvider.createDevice": {
|
|
71324
72047
|
capName: "device-provider",
|
|
71325
72048
|
capScope: "system",
|
|
@@ -71348,6 +72071,13 @@ Object.freeze({
|
|
|
71348
72071
|
access: "view",
|
|
71349
72072
|
role: "admin"
|
|
71350
72073
|
},
|
|
72074
|
+
"deviceProvider.getDiscoveryModes": {
|
|
72075
|
+
capName: "device-provider",
|
|
72076
|
+
capScope: "system",
|
|
72077
|
+
addonId: null,
|
|
72078
|
+
access: "view",
|
|
72079
|
+
role: "admin"
|
|
72080
|
+
},
|
|
71351
72081
|
"deviceProvider.getDiscoveryParamsSchema": {
|
|
71352
72082
|
capName: "device-provider",
|
|
71353
72083
|
capScope: "system",
|
|
@@ -72125,6 +72855,13 @@ Object.freeze({
|
|
|
72125
72855
|
access: "create",
|
|
72126
72856
|
role: "admin"
|
|
72127
72857
|
},
|
|
72858
|
+
"keychain.releaseRecordRefs": {
|
|
72859
|
+
capName: "keychain",
|
|
72860
|
+
capScope: "system",
|
|
72861
|
+
addonId: null,
|
|
72862
|
+
access: "create",
|
|
72863
|
+
role: "admin"
|
|
72864
|
+
},
|
|
72128
72865
|
"keychain.resolve": {
|
|
72129
72866
|
capName: "keychain",
|
|
72130
72867
|
capScope: "system",
|
|
@@ -72545,6 +73282,13 @@ Object.freeze({
|
|
|
72545
73282
|
access: "view",
|
|
72546
73283
|
role: "admin"
|
|
72547
73284
|
},
|
|
73285
|
+
"localNetwork.getScanSubnets": {
|
|
73286
|
+
capName: "local-network",
|
|
73287
|
+
capScope: "system",
|
|
73288
|
+
addonId: null,
|
|
73289
|
+
access: "view",
|
|
73290
|
+
role: "admin"
|
|
73291
|
+
},
|
|
72548
73292
|
"localNetwork.getTlsStatus": {
|
|
72549
73293
|
capName: "local-network",
|
|
72550
73294
|
capScope: "system",
|
|
@@ -72594,6 +73338,13 @@ Object.freeze({
|
|
|
72594
73338
|
access: "create",
|
|
72595
73339
|
role: "admin"
|
|
72596
73340
|
},
|
|
73341
|
+
"localNetwork.scanNetwork": {
|
|
73342
|
+
capName: "local-network",
|
|
73343
|
+
capScope: "system",
|
|
73344
|
+
addonId: null,
|
|
73345
|
+
access: "create",
|
|
73346
|
+
role: "admin"
|
|
73347
|
+
},
|
|
72597
73348
|
"localNetwork.setAddressRole": {
|
|
72598
73349
|
capName: "local-network",
|
|
72599
73350
|
capScope: "system",
|
|
@@ -72615,6 +73366,13 @@ Object.freeze({
|
|
|
72615
73366
|
access: "create",
|
|
72616
73367
|
role: "admin"
|
|
72617
73368
|
},
|
|
73369
|
+
"localNetwork.setScanSubnets": {
|
|
73370
|
+
capName: "local-network",
|
|
73371
|
+
capScope: "system",
|
|
73372
|
+
addonId: null,
|
|
73373
|
+
access: "create",
|
|
73374
|
+
role: "admin"
|
|
73375
|
+
},
|
|
72618
73376
|
"localNetwork.setViewerEndpoints": {
|
|
72619
73377
|
capName: "local-network",
|
|
72620
73378
|
capScope: "system",
|
|
@@ -76836,6 +77594,13 @@ Object.freeze({
|
|
|
76836
77594
|
access: "create",
|
|
76837
77595
|
role: "admin"
|
|
76838
77596
|
},
|
|
77597
|
+
"storageAdmin.dropOrphanedKind": {
|
|
77598
|
+
capName: "storage-admin",
|
|
77599
|
+
capScope: "system",
|
|
77600
|
+
addonId: null,
|
|
77601
|
+
access: "delete",
|
|
77602
|
+
role: "admin"
|
|
77603
|
+
},
|
|
76839
77604
|
"storageAdmin.listKinds": {
|
|
76840
77605
|
capName: "storage-admin",
|
|
76841
77606
|
capScope: "system",
|
|
@@ -76857,6 +77622,27 @@ Object.freeze({
|
|
|
76857
77622
|
access: "view",
|
|
76858
77623
|
role: "admin"
|
|
76859
77624
|
},
|
|
77625
|
+
"storageAdmin.scanStaleData": {
|
|
77626
|
+
capName: "storage-admin",
|
|
77627
|
+
capScope: "system",
|
|
77628
|
+
addonId: null,
|
|
77629
|
+
access: "create",
|
|
77630
|
+
role: "admin"
|
|
77631
|
+
},
|
|
77632
|
+
"storageAdmin.staleDataReport": {
|
|
77633
|
+
capName: "storage-admin",
|
|
77634
|
+
capScope: "system",
|
|
77635
|
+
addonId: null,
|
|
77636
|
+
access: "view",
|
|
77637
|
+
role: "admin"
|
|
77638
|
+
},
|
|
77639
|
+
"storageAdmin.unsetStaleSettingsKey": {
|
|
77640
|
+
capName: "storage-admin",
|
|
77641
|
+
capScope: "system",
|
|
77642
|
+
addonId: null,
|
|
77643
|
+
access: "create",
|
|
77644
|
+
role: "admin"
|
|
77645
|
+
},
|
|
76860
77646
|
"storageEvictable.evict": {
|
|
76861
77647
|
capName: "storage-evictable",
|
|
76862
77648
|
capScope: "system",
|