@camstack/addon-provider-dreame 0.2.101 → 0.2.102

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/dist/addon.js CHANGED
@@ -58019,7 +58019,7 @@ var ZodIssueCode = {
58019
58019
  var ZodFirstPartyTypeKind;
58020
58020
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
58021
58021
  //#endregion
58022
- //#region ../types/dist/sleep-CnLyvg3w.mjs
58022
+ //#region ../types/dist/sleep-DBKu2-U5.mjs
58023
58023
  /**
58024
58024
  * The audio chunk plane's byte format, and the ONE expansion from a coded
58025
58025
  * window to float samples (D455).
@@ -60048,7 +60048,23 @@ var EncodeProfileSchema = object({
60048
60048
  "zerolatency",
60049
60049
  "film",
60050
60050
  "animation"
60051
- ]).optional()
60051
+ ]).optional(),
60052
+ /**
60053
+ * ONE slice per access unit.
60054
+ *
60055
+ * `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
60056
+ * the encoder as five NAL slices that share one RTP timestamp and carry one
60057
+ * marker bit. A libwebrtc depacketiser sees five frame-starts and one
60058
+ * frame-end per frame: the first pictures render and the video then freezes
60059
+ * for good while the audio, on its own plane, plays on. Measured on this hub
60060
+ * 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
60061
+ *
60062
+ * A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
60063
+ * `outputArgs` on purpose: an opaque array is part of the sharing key, so two
60064
+ * consumers meaning the same thing spelled differently would stop sharing one
60065
+ * child. Absent means "whatever the encoder does" — today's behaviour.
60066
+ */
60067
+ singleSlicePerFrame: boolean().optional()
60052
60068
  }),
60053
60069
  audio: union([literal("passthrough"), object({
60054
60070
  codec: _enum([
@@ -60098,7 +60114,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
60098
60114
  audio: "passthrough"
60099
60115
  };
60100
60116
  ({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
60101
- ({ ...BASE_LIVE_EGRESS_PROFILE });
60117
+ ({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
60102
60118
  /**
60103
60119
  * Deep wiring healthcheck — snapshot of active reachability probes across
60104
60120
  * every declared capability + widget of every installed plugin, on every
@@ -72820,13 +72836,109 @@ var SummariesQueryInput = object({
72820
72836
  deviceIds: array(number()).min(1),
72821
72837
  since: number().optional(),
72822
72838
  until: number().optional(),
72823
- limit: number().int().min(1).max(200).default(50)
72839
+ limit: number().int().min(1).max(200).default(50),
72840
+ /** The same member-wise filter {@link listRecentSummaries} takes — one
72841
+ * meaning of "dog" on every summary surface. */
72842
+ classes: array(string().min(1).max(60)).max(40).optional()
72824
72843
  });
72825
- var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
72826
72844
  var SummaryDetailSchema = object({
72827
72845
  summary: SummarySchema,
72828
- /** Member track ids, in absorption order. */
72829
- trackIds: array(string()).readonly()
72846
+ /** Members in absorption order, oldest join first. */
72847
+ members: array(object({
72848
+ trackId: string(),
72849
+ /**
72850
+ * The track's class at the time it JOINED, or `null` when it was unresolved
72851
+ * and the track no longer exists to fill it.
72852
+ *
72853
+ * The join, not the latest opinion: class voting can re-decide a track's
72854
+ * class afterwards, and a group's composition is the history of who came
72855
+ * together. A consumer counts these to badge a thumbnail — "two people and a
72856
+ * dog" — rather than being handed a second, denormalised tally that would
72857
+ * drift from the members it claims to describe.
72858
+ */
72859
+ className: string().nullable(),
72860
+ /** `primary` is the one member that carries the group's identity. */
72861
+ role: _enum([
72862
+ "primary",
72863
+ "sibling",
72864
+ "child"
72865
+ ]).nullable(),
72866
+ joinedAt: number(),
72867
+ /** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
72868
+ * at read time. Absent when nothing resolved, never an empty string. */
72869
+ label: string().optional(),
72870
+ /** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
72871
+ * recognised nobody, and absent for a member whose track has been pruned —
72872
+ * a thumbnail that names the wrong person is worse than one naming nobody. */
72873
+ subLabel: string().optional()
72874
+ })).readonly()
72875
+ });
72876
+ /**
72877
+ * What a LIST of groups carries: the envelope plus what it is MADE OF.
72878
+ *
72879
+ * Coarse on purpose — the operator's rule is "only the rough data on the list,
72880
+ * we extend when we notice we need more". Enough to draw the card ("two people
72881
+ * and a dog") and no more. The MEMBERS, their names and the per-member links
72882
+ * are on {@link getSummary}: shipping every member of every group so a client
72883
+ * can count them turns a page of two hundred groups into a thousand records to
72884
+ * draw two hundred badges.
72885
+ */
72886
+ var SummaryListItemSchema = object({
72887
+ summary: SummarySchema,
72888
+ /** Class counts, most numerous first; `className: null` is a member whose
72889
+ * class never resolved, counted so the counts add up to `memberCount`. */
72890
+ classes: array(object({
72891
+ className: string().nullable(),
72892
+ count: number().int().positive()
72893
+ })).readonly()
72894
+ });
72895
+ var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
72896
+ /**
72897
+ * The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
72898
+ *
72899
+ * The reel on the cameras page and the Events gallery both ride a cursor, so a
72900
+ * summaries feed that could only answer "the last N for these cameras"
72901
+ * (`listSummaries`) would make groups available in the timeline and nowhere
72902
+ * else. Two feeds with different ordering contracts would be two ideas of what
72903
+ * "newest" means, on one screen.
72904
+ */
72905
+ var RecentSummariesQueryInput = object({
72906
+ /** Devices to merge. An empty array yields an empty page. */
72907
+ deviceIds: array(number()),
72908
+ /** Window lower bound on `lastActiveAt` (inclusive). */
72909
+ since: number().optional(),
72910
+ /** Window upper bound on `lastActiveAt` (inclusive). */
72911
+ until: number().optional(),
72912
+ limit: number().int().min(1).max(500).default(100),
72913
+ /** Opaque continuation cursor from a previous page's `nextCursor`. */
72914
+ cursor: string().optional(),
72915
+ /**
72916
+ * Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
72917
+ * deliberately the same name: the events filter tree emits one list of ticked
72918
+ * taxonomy nodes, and a summaries feed that called it something else would
72919
+ * make the operator's one filter component produce two shapes.
72920
+ *
72921
+ * A question about the MEMBERS: a group matches when ANY of them does. "Show
72922
+ * me the arrivals with a dog" has to return the group of four people who had
72923
+ * one with them; a filter on the group's own fields could only ever answer
72924
+ * about its primary.
72925
+ *
72926
+ * Matched against all THREE tiers of a member — the class (`animal`), the
72927
+ * sub-class (`dog`) and the instance (a name, a plate) — because which tier a
72928
+ * ticked node lives on is the taxonomy's business, not the caller's. `dog` is
72929
+ * an event kind in the tree and a tier-1 label on an `animal` track; a filter
72930
+ * that read only the class would answer "animal" and never "dog".
72931
+ *
72932
+ * ABSENT or EMPTY means no filter — absent is not a selection of none.
72933
+ */
72934
+ classes: array(string().min(1).max(60)).max(40).optional()
72935
+ });
72936
+ var RecentSummariesPageSchema = object({
72937
+ /** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
72938
+ * {@link listSummaries} — one list shape, so a card renders the same
72939
+ * whichever feed drew it. */
72940
+ summaries: array(SummaryListItemSchema).readonly(),
72941
+ nextCursor: string().nullable()
72830
72942
  });
72831
72943
  var RecentTracksPageSchema = object({
72832
72944
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -73240,7 +73352,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
73240
73352
  classes: array(string()).optional(),
73241
73353
  /** See {@link ExcludeSourcesDoc}. */
73242
73354
  excludeSources: array(TrackSourceSchema).optional()
73243
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
73355
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
73244
73356
  kind: "mutation",
73245
73357
  auth: "admin"
73246
73358
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -85166,7 +85278,29 @@ var LoggingSettingsPatchSchema = object({
85166
85278
  * disarmed the channels it did not mention would make the Levels page and
85167
85279
  * the Diagnostics page fight over the same value.
85168
85280
  */
85169
- channels: array(LogChannelWindowPatchSchema).readonly().optional()
85281
+ channels: array(LogChannelWindowPatchSchema).readonly().optional(),
85282
+ /**
85283
+ * How many days the analytics OPS LOG is kept — the audit trail of what
85284
+ * retention actually deleted.
85285
+ *
85286
+ * It lives HERE, on the logging document, and not on the analytics addon's
85287
+ * settings form, on the operator's instruction: every other log-ish window in
85288
+ * this system is configured through this one document, and a retention audit
85289
+ * configured somewhere else is a second place to look when the question is
85290
+ * "what happened to my data".
85291
+ *
85292
+ * That placement has a cost worth stating: this document ships in the
85293
+ * framework closure, so this knob needs a published `@camstack/server` while
85294
+ * the four windows beside it (D485) reach a node on `camstack deploy`.
85295
+ *
85296
+ * `retention-model.ts` argued this one must NOT follow a device window,
85297
+ * because the audit trail is the history of the SWEEP and not of the camera.
85298
+ * That argument stands and is untouched — what changes is that 30 days stops
85299
+ * being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
85300
+ * rather than 0-as-delete: an audit log truncated to nothing is precisely the
85301
+ * state in which the next 9.5 GiB leak cannot be explained.
85302
+ */
85303
+ opsLogRetentionDays: number().int().min(0).max(3650).optional()
85170
85304
  });
85171
85305
  /**
85172
85306
  * Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
@@ -85239,6 +85373,14 @@ var LoggingSettingsStateSchema = object({
85239
85373
  channels: array(LogChannelDescriptorSchema).readonly(),
85240
85374
  /** The channels ARMED right now, each with its deadline. */
85241
85375
  activeChannels: array(LogChannelWindowStateSchema).readonly(),
85376
+ /**
85377
+ * The ops-log window in days, as it is in force. `0` = kept forever.
85378
+ *
85379
+ * Reported rather than left to the caller's memory of what it wrote: this is
85380
+ * the value the analytics sweep will actually use, and an operator asking how
85381
+ * long their audit trail lives should not have to infer it from a default.
85382
+ */
85383
+ opsLogRetentionDays: number().int().min(0),
85242
85384
  persisted: boolean()
85243
85385
  });
85244
85386
  method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
@@ -91239,6 +91381,12 @@ Object.freeze({
91239
91381
  addonId: null,
91240
91382
  access: "view"
91241
91383
  },
91384
+ "pipelineAnalytics.listRecentSummaries": {
91385
+ capName: "pipeline-analytics",
91386
+ capScope: "device",
91387
+ addonId: null,
91388
+ access: "view"
91389
+ },
91242
91390
  "pipelineAnalytics.listRecentTracks": {
91243
91391
  capName: "pipeline-analytics",
91244
91392
  capScope: "device",
@@ -95066,6 +95214,11 @@ Object.freeze({
95066
95214
  form: "single",
95067
95215
  optional: true
95068
95216
  }],
95217
+ "pipelineAnalytics.listRecentSummaries": [{
95218
+ name: "deviceIds",
95219
+ form: "array",
95220
+ optional: false
95221
+ }],
95069
95222
  "pipelineAnalytics.listRecentTracks": [{
95070
95223
  name: "deviceIds",
95071
95224
  form: "array",
package/dist/addon.mjs CHANGED
@@ -58016,7 +58016,7 @@ var ZodIssueCode = {
58016
58016
  var ZodFirstPartyTypeKind;
58017
58017
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
58018
58018
  //#endregion
58019
- //#region ../types/dist/sleep-CnLyvg3w.mjs
58019
+ //#region ../types/dist/sleep-DBKu2-U5.mjs
58020
58020
  /**
58021
58021
  * The audio chunk plane's byte format, and the ONE expansion from a coded
58022
58022
  * window to float samples (D455).
@@ -60045,7 +60045,23 @@ var EncodeProfileSchema = object({
60045
60045
  "zerolatency",
60046
60046
  "film",
60047
60047
  "animation"
60048
- ]).optional()
60048
+ ]).optional(),
60049
+ /**
60050
+ * ONE slice per access unit.
60051
+ *
60052
+ * `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
60053
+ * the encoder as five NAL slices that share one RTP timestamp and carry one
60054
+ * marker bit. A libwebrtc depacketiser sees five frame-starts and one
60055
+ * frame-end per frame: the first pictures render and the video then freezes
60056
+ * for good while the audio, on its own plane, plays on. Measured on this hub
60057
+ * 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
60058
+ *
60059
+ * A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
60060
+ * `outputArgs` on purpose: an opaque array is part of the sharing key, so two
60061
+ * consumers meaning the same thing spelled differently would stop sharing one
60062
+ * child. Absent means "whatever the encoder does" — today's behaviour.
60063
+ */
60064
+ singleSlicePerFrame: boolean().optional()
60049
60065
  }),
60050
60066
  audio: union([literal("passthrough"), object({
60051
60067
  codec: _enum([
@@ -60095,7 +60111,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
60095
60111
  audio: "passthrough"
60096
60112
  };
60097
60113
  ({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
60098
- ({ ...BASE_LIVE_EGRESS_PROFILE });
60114
+ ({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
60099
60115
  /**
60100
60116
  * Deep wiring healthcheck — snapshot of active reachability probes across
60101
60117
  * every declared capability + widget of every installed plugin, on every
@@ -72817,13 +72833,109 @@ var SummariesQueryInput = object({
72817
72833
  deviceIds: array(number()).min(1),
72818
72834
  since: number().optional(),
72819
72835
  until: number().optional(),
72820
- limit: number().int().min(1).max(200).default(50)
72836
+ limit: number().int().min(1).max(200).default(50),
72837
+ /** The same member-wise filter {@link listRecentSummaries} takes — one
72838
+ * meaning of "dog" on every summary surface. */
72839
+ classes: array(string().min(1).max(60)).max(40).optional()
72821
72840
  });
72822
- var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
72823
72841
  var SummaryDetailSchema = object({
72824
72842
  summary: SummarySchema,
72825
- /** Member track ids, in absorption order. */
72826
- trackIds: array(string()).readonly()
72843
+ /** Members in absorption order, oldest join first. */
72844
+ members: array(object({
72845
+ trackId: string(),
72846
+ /**
72847
+ * The track's class at the time it JOINED, or `null` when it was unresolved
72848
+ * and the track no longer exists to fill it.
72849
+ *
72850
+ * The join, not the latest opinion: class voting can re-decide a track's
72851
+ * class afterwards, and a group's composition is the history of who came
72852
+ * together. A consumer counts these to badge a thumbnail — "two people and a
72853
+ * dog" — rather than being handed a second, denormalised tally that would
72854
+ * drift from the members it claims to describe.
72855
+ */
72856
+ className: string().nullable(),
72857
+ /** `primary` is the one member that carries the group's identity. */
72858
+ role: _enum([
72859
+ "primary",
72860
+ "sibling",
72861
+ "child"
72862
+ ]).nullable(),
72863
+ joinedAt: number(),
72864
+ /** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
72865
+ * at read time. Absent when nothing resolved, never an empty string. */
72866
+ label: string().optional(),
72867
+ /** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
72868
+ * recognised nobody, and absent for a member whose track has been pruned —
72869
+ * a thumbnail that names the wrong person is worse than one naming nobody. */
72870
+ subLabel: string().optional()
72871
+ })).readonly()
72872
+ });
72873
+ /**
72874
+ * What a LIST of groups carries: the envelope plus what it is MADE OF.
72875
+ *
72876
+ * Coarse on purpose — the operator's rule is "only the rough data on the list,
72877
+ * we extend when we notice we need more". Enough to draw the card ("two people
72878
+ * and a dog") and no more. The MEMBERS, their names and the per-member links
72879
+ * are on {@link getSummary}: shipping every member of every group so a client
72880
+ * can count them turns a page of two hundred groups into a thousand records to
72881
+ * draw two hundred badges.
72882
+ */
72883
+ var SummaryListItemSchema = object({
72884
+ summary: SummarySchema,
72885
+ /** Class counts, most numerous first; `className: null` is a member whose
72886
+ * class never resolved, counted so the counts add up to `memberCount`. */
72887
+ classes: array(object({
72888
+ className: string().nullable(),
72889
+ count: number().int().positive()
72890
+ })).readonly()
72891
+ });
72892
+ var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
72893
+ /**
72894
+ * The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
72895
+ *
72896
+ * The reel on the cameras page and the Events gallery both ride a cursor, so a
72897
+ * summaries feed that could only answer "the last N for these cameras"
72898
+ * (`listSummaries`) would make groups available in the timeline and nowhere
72899
+ * else. Two feeds with different ordering contracts would be two ideas of what
72900
+ * "newest" means, on one screen.
72901
+ */
72902
+ var RecentSummariesQueryInput = object({
72903
+ /** Devices to merge. An empty array yields an empty page. */
72904
+ deviceIds: array(number()),
72905
+ /** Window lower bound on `lastActiveAt` (inclusive). */
72906
+ since: number().optional(),
72907
+ /** Window upper bound on `lastActiveAt` (inclusive). */
72908
+ until: number().optional(),
72909
+ limit: number().int().min(1).max(500).default(100),
72910
+ /** Opaque continuation cursor from a previous page's `nextCursor`. */
72911
+ cursor: string().optional(),
72912
+ /**
72913
+ * Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
72914
+ * deliberately the same name: the events filter tree emits one list of ticked
72915
+ * taxonomy nodes, and a summaries feed that called it something else would
72916
+ * make the operator's one filter component produce two shapes.
72917
+ *
72918
+ * A question about the MEMBERS: a group matches when ANY of them does. "Show
72919
+ * me the arrivals with a dog" has to return the group of four people who had
72920
+ * one with them; a filter on the group's own fields could only ever answer
72921
+ * about its primary.
72922
+ *
72923
+ * Matched against all THREE tiers of a member — the class (`animal`), the
72924
+ * sub-class (`dog`) and the instance (a name, a plate) — because which tier a
72925
+ * ticked node lives on is the taxonomy's business, not the caller's. `dog` is
72926
+ * an event kind in the tree and a tier-1 label on an `animal` track; a filter
72927
+ * that read only the class would answer "animal" and never "dog".
72928
+ *
72929
+ * ABSENT or EMPTY means no filter — absent is not a selection of none.
72930
+ */
72931
+ classes: array(string().min(1).max(60)).max(40).optional()
72932
+ });
72933
+ var RecentSummariesPageSchema = object({
72934
+ /** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
72935
+ * {@link listSummaries} — one list shape, so a card renders the same
72936
+ * whichever feed drew it. */
72937
+ summaries: array(SummaryListItemSchema).readonly(),
72938
+ nextCursor: string().nullable()
72827
72939
  });
72828
72940
  var RecentTracksPageSchema = object({
72829
72941
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -73237,7 +73349,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
73237
73349
  classes: array(string()).optional(),
73238
73350
  /** See {@link ExcludeSourcesDoc}. */
73239
73351
  excludeSources: array(TrackSourceSchema).optional()
73240
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
73352
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
73241
73353
  kind: "mutation",
73242
73354
  auth: "admin"
73243
73355
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -85163,7 +85275,29 @@ var LoggingSettingsPatchSchema = object({
85163
85275
  * disarmed the channels it did not mention would make the Levels page and
85164
85276
  * the Diagnostics page fight over the same value.
85165
85277
  */
85166
- channels: array(LogChannelWindowPatchSchema).readonly().optional()
85278
+ channels: array(LogChannelWindowPatchSchema).readonly().optional(),
85279
+ /**
85280
+ * How many days the analytics OPS LOG is kept — the audit trail of what
85281
+ * retention actually deleted.
85282
+ *
85283
+ * It lives HERE, on the logging document, and not on the analytics addon's
85284
+ * settings form, on the operator's instruction: every other log-ish window in
85285
+ * this system is configured through this one document, and a retention audit
85286
+ * configured somewhere else is a second place to look when the question is
85287
+ * "what happened to my data".
85288
+ *
85289
+ * That placement has a cost worth stating: this document ships in the
85290
+ * framework closure, so this knob needs a published `@camstack/server` while
85291
+ * the four windows beside it (D485) reach a node on `camstack deploy`.
85292
+ *
85293
+ * `retention-model.ts` argued this one must NOT follow a device window,
85294
+ * because the audit trail is the history of the SWEEP and not of the camera.
85295
+ * That argument stands and is untouched — what changes is that 30 days stops
85296
+ * being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
85297
+ * rather than 0-as-delete: an audit log truncated to nothing is precisely the
85298
+ * state in which the next 9.5 GiB leak cannot be explained.
85299
+ */
85300
+ opsLogRetentionDays: number().int().min(0).max(3650).optional()
85167
85301
  });
85168
85302
  /**
85169
85303
  * Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
@@ -85236,6 +85370,14 @@ var LoggingSettingsStateSchema = object({
85236
85370
  channels: array(LogChannelDescriptorSchema).readonly(),
85237
85371
  /** The channels ARMED right now, each with its deadline. */
85238
85372
  activeChannels: array(LogChannelWindowStateSchema).readonly(),
85373
+ /**
85374
+ * The ops-log window in days, as it is in force. `0` = kept forever.
85375
+ *
85376
+ * Reported rather than left to the caller's memory of what it wrote: this is
85377
+ * the value the analytics sweep will actually use, and an operator asking how
85378
+ * long their audit trail lives should not have to infer it from a default.
85379
+ */
85380
+ opsLogRetentionDays: number().int().min(0),
85239
85381
  persisted: boolean()
85240
85382
  });
85241
85383
  method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
@@ -91236,6 +91378,12 @@ Object.freeze({
91236
91378
  addonId: null,
91237
91379
  access: "view"
91238
91380
  },
91381
+ "pipelineAnalytics.listRecentSummaries": {
91382
+ capName: "pipeline-analytics",
91383
+ capScope: "device",
91384
+ addonId: null,
91385
+ access: "view"
91386
+ },
91239
91387
  "pipelineAnalytics.listRecentTracks": {
91240
91388
  capName: "pipeline-analytics",
91241
91389
  capScope: "device",
@@ -95063,6 +95211,11 @@ Object.freeze({
95063
95211
  form: "single",
95064
95212
  optional: true
95065
95213
  }],
95214
+ "pipelineAnalytics.listRecentSummaries": [{
95215
+ name: "deviceIds",
95216
+ form: "array",
95217
+ optional: false
95218
+ }],
95066
95219
  "pipelineAnalytics.listRecentTracks": [{
95067
95220
  name: "deviceIds",
95068
95221
  form: "array",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-dreame",
3
- "version": "0.2.101",
3
+ "version": "0.2.102",
4
4
  "description": "Dreame robot-vacuum / lawn-mower device-provider addon for CamStack — wraps the @apocaliss92/nodedreame Dreamehome cloud client",
5
5
  "keywords": [
6
6
  "camstack",