@camstack/system 1.2.200 → 1.2.202

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.
Files changed (57) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +38 -9
  8. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +234 -81
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +234 -81
  10. package/dist/builtins/backup-orchestrator/destination-policy.d.ts +32 -14
  11. package/dist/builtins/backup-orchestrator/schedule-store.d.ts +12 -2
  12. package/dist/builtins/console-logging/index.js +1 -1
  13. package/dist/builtins/console-logging/index.mjs +1 -1
  14. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  15. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  16. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  17. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  18. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  19. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  20. package/dist/builtins/hub-forwarder/index.js +1 -1
  21. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  22. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  23. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  24. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  25. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  26. package/dist/builtins/local-network/local-network.addon.js +1 -1
  27. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  28. package/dist/builtins/loki-logging/index.js +1 -1
  29. package/dist/builtins/loki-logging/index.mjs +1 -1
  30. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  31. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  32. package/dist/builtins/platform-probe/index.js +1 -1
  33. package/dist/builtins/platform-probe/index.mjs +1 -1
  34. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  35. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  36. package/dist/builtins/snapshot/index.js +1 -1
  37. package/dist/builtins/snapshot/index.mjs +1 -1
  38. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  39. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  40. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  41. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  42. package/dist/builtins/storage-orchestrator/location-store.d.ts +12 -3
  43. package/dist/builtins/storage-orchestrator/storage-migration-coordinator.d.ts +9 -9
  44. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +181 -129
  45. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +181 -129
  46. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +54 -31
  47. package/dist/builtins/system-config/system-config.addon.js +1 -1
  48. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  49. package/dist/builtins/winston-logging/index.js +1 -1
  50. package/dist/builtins/winston-logging/index.mjs +1 -1
  51. package/dist/{dist-CCp74QLJ.mjs → dist-CiHYspij.mjs} +235 -199
  52. package/dist/{dist-KQ5D2wqr.js → dist-jZb-HKI5.js} +246 -198
  53. package/dist/index.js +1 -1
  54. package/dist/index.mjs +1 -1
  55. package/dist/{retired-settings-keys-7P9XwNdl.mjs → retired-settings-keys-DeRxo3vg.mjs} +1 -1
  56. package/dist/{retired-settings-keys-2lWk7OeU.js → retired-settings-keys-Dxv9S_lO.js} +1 -1
  57. package/package.json +1 -1
@@ -3815,111 +3815,6 @@ function logLevelAtMost(level, threshold) {
3815
3815
  return LOG_LEVEL_RANK[level] <= LOG_LEVEL_RANK[threshold];
3816
3816
  }
3817
3817
  /**
3818
- * Per-component log CHANNELS — the gate a hot path consults, and the registry
3819
- * an addon declares its channels in.
3820
- *
3821
- * ## Two axes, deliberately separated
3822
- *
3823
- * - **DECLARATION** — which channels exist. Only the addon knows:
3824
- * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
3825
- * baichuan/handshake. A hand-wired central list rots at the first addition,
3826
- * and rots silently. So a channel is declared where it is consulted, and the
3827
- * `log-channels` capability enumerates the declarations.
3828
- * - **VALUE** — at which level, for which scope, until when. That stays ONE
3829
- * thing: the logging settings document on the `system` cap. Two authorities
3830
- * over the values is the exact defect
3831
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
3832
- * remove; re-introducing it from the cure side would be grotesque.
3833
- *
3834
- * Nothing in this file reads a clock, an env var or a store. The registry is
3835
- * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
3836
- * the hot path with a value somebody actually read, and by
3837
- * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
3838
- * never reaches here, so it can neither disarm an armed channel nor arm a
3839
- * disarmed one (D49).
3840
- *
3841
- * ## The canonical call shape
3842
- *
3843
- * ```ts
3844
- * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
3845
- * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
3846
- * }
3847
- * ```
3848
- *
3849
- * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
3850
- * read. Disarmed, a call site costs one load and one branch, and the `extras`
3851
- * object literal is never constructed because it lives inside the branch. It
3852
- * is the same shape already proven in production at `stream-broker.ts:1650`,
3853
- * and the same discipline `LoggingGate.allowsDestination` uses for the
3854
- * destination floor (measured at 1.93 ns/call when off).
3855
- *
3856
- * ## Why a channel emits at `info`
3857
- *
3858
- * `loki-logging.addon.ts` pins the destination default at `info` and
3859
- * `loki-destination.ts` drops everything below it, so a line emitted at
3860
- * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
3861
- * minutes. A diagnostic that cannot be read an hour later is worse than no
3862
- * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
3863
- * emits at the channel's declared level, whose schema floor is `info`.
3864
- */
3865
- /**
3866
- * The level a channel writes at once armed.
3867
- *
3868
- * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
3869
- * not leave the process for Loki, and the whole point of arming a channel is
3870
- * to read it later.
3871
- */
3872
- var LogChannelLevelSchema = z.enum([
3873
- "info",
3874
- "warn",
3875
- "error"
3876
- ]);
3877
- /**
3878
- * What an addon declares about one channel. No value, no state — a
3879
- * declaration is inert.
3880
- */
3881
- var LogChannelDescriptorSchema = z.object({
3882
- /**
3883
- * Dotted `area.thing`, unique across the workspace. `area` is conventionally
3884
- * the addon's short name so an operator reading a channel list can tell who
3885
- * owns it without a second lookup.
3886
- */
3887
- name: z.string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
3888
- /** One sentence: what the operator will SEE after arming it. */
3889
- description: z.string().min(1),
3890
- /** The level its lines are emitted at. Never below `info`. */
3891
- defaultLevel: LogChannelLevelSchema,
3892
- /**
3893
- * Whether this channel can be narrowed to a camera.
3894
- *
3895
- * `true` is a PROMISE with two halves, and both must hold: the gate is
3896
- * consulted with the numeric device id, AND every line the channel admits
3897
- * carries `tags: { deviceId }` with that same numeric id. The second half is
3898
- * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
3899
- * keeps `deviceId` out of the stream labels for cardinality, so the tag in
3900
- * the body is the only way to filter.
3901
- *
3902
- * A channel whose lines carry the device only in `meta` (or not at all) is
3903
- * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
3904
- * the operator narrows to one camera, sees nothing, and concludes the code
3905
- * path was never taken.
3906
- */
3907
- perDevice: z.boolean()
3908
- });
3909
- /**
3910
- * An armed window over one channel, as the document hands it to a mirror.
3911
- *
3912
- * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
3913
- * expires by itself, which is the one failure a boolean cannot avoid.
3914
- */
3915
- var LogChannelWindowSchema = z.object({
3916
- channel: z.string().min(1),
3917
- /** Epoch ms the window closes at. */
3918
- armedUntilMs: z.number(),
3919
- /** `null` = every camera. A non-empty list narrows to those numeric ids. */
3920
- deviceIds: z.array(z.number().int()).readonly().nullable()
3921
- });
3922
- /**
3923
3818
  * Ops-log — the durable, append-only operations audit shared by the
3924
3819
  * recordings and events management surfaces.
3925
3820
  *
@@ -4897,8 +4792,11 @@ var StorageLocationTypeSchema = z.string().regex(/^[a-z][a-zA-Z0-9-]*$/);
4897
4792
  * `STORAGE_LOCATION_CARDINALITY` map has been removed.
4898
4793
  *
4899
4794
  * `id` is a stable namespaced string of the form `<type>:<slug>`.
4900
- * The default location for a type uses `id === <type>:default` by
4901
- * convention (the bare type ref like `'backups'` resolves to it).
4795
+ * The seed names its first instance `<type>:default` — a NAME, not a flag.
4796
+ * There is no default location any more (D383): `enabled` is the whole write
4797
+ * model, and a bare type ref resolves to the sole location of the type, or —
4798
+ * transitionally, only while legacy NULL-stamped rows exist — to the row whose
4799
+ * slug is `default`.
4902
4800
  *
4903
4801
  * `isSystem` is a legacy persisted flag. Seed still creates the initial
4904
4802
  * `<type>:default` locations; the flag is no longer a lock, a badge, or a
@@ -4919,21 +4817,20 @@ var StorageLocationSchema = z.object({
4919
4817
  * flag at upsert time, not here (the schema is provider-agnostic).
4920
4818
  */
4921
4819
  nodeId: z.string().optional(),
4922
- isDefault: z.boolean().default(false),
4923
4820
  isSystem: z.boolean().default(false),
4924
4821
  /**
4925
- * Operator opt-in: whether consumers that BALANCE across several locations
4926
- * of a type may write here. Recordings reads it today; event media and
4927
- * backups are the next consumers, which is why the flag lives on the
4928
- * location rather than in any one addon's store — nothing has to be
4929
- * extended to add the next consumer.
4822
+ * THE write switch, and the only one (D383). `enabled: true` means every
4823
+ * consumer that chooses a write target for this type may write here, and all
4824
+ * enabled locations of a type are used TOGETHER; `false` means read-only —
4825
+ * still read, still played back, still age-swept, still drained, never
4826
+ * written.
4930
4827
  *
4931
- * OPTIONAL, and ABSENT MEANS ACTIVE. Every location persisted before the
4932
- * flag existed reads back with no flag and keeps working exactly as before;
4933
- * that is the whole compat story, and it is why no migration ships with it.
4934
- * A newly CREATED sibling is stamped `false` by the orchestrator (creating a
4935
- * disk must not silently start writing to it); the default of a type is
4936
- * always stamped `true`.
4828
+ * OPTIONAL only for the wire: an upsert that omits it means "leave what is
4829
+ * stored" on an update and "born inert unless it is the first location of its
4830
+ * type" on a create. On a PERSISTED row absence is legacy and it means
4831
+ * enabled — {@link isLocationEnabled} is the one place that says so, and the
4832
+ * orchestrator stamps every flagless row `true` once at hydrate so absence
4833
+ * stops existing rather than being re-derived on every read.
4937
4834
  */
4938
4835
  enabled: z.boolean().optional(),
4939
4836
  /** COMPUTED at read time by the orchestrator (statfs of the backing volume
@@ -4947,9 +4844,31 @@ var StorageLocationSchema = z.object({
4947
4844
  updatedAt: z.number()
4948
4845
  });
4949
4846
  /**
4847
+ * The retired `isDefault` key, DECLARED rather than dropped.
4848
+ *
4849
+ * A key removed from a non-strict `z.object` is stripped in silence (D380,
4850
+ * D381): a reader that still needs the old value gets `undefined` and cannot
4851
+ * tell "absent" from "never sent". The one reader that legitimately needs it —
4852
+ * the location store's boot migration, which turns the old default flag into
4853
+ * the `enabled` write set — parses THIS schema against the raw row instead, so
4854
+ * the migration is explicit and the live schema stays clean. Nothing else in
4855
+ * the repo may read it; `scripts/check-no-storage-default.ts` enforces that.
4856
+ */
4857
+ var LegacyStorageLocationDefaultSchema = z.object({ isDefault: z.boolean().optional() });
4858
+ /**
4859
+ * Is this location a write target? THE one place that decides what an absent
4860
+ * `enabled` means on a persisted row — legacy rows predate the flag and were
4861
+ * active, so absence is enabled. Every consumer asks here rather than spelling
4862
+ * `enabled !== false` again, so the tri-state has exactly one interpretation.
4863
+ */
4864
+ function isLocationEnabled(location) {
4865
+ return location.enabled !== false;
4866
+ }
4867
+ /**
4950
4868
  * Reference accepted by consumer-facing `api.storage.*` calls.
4951
4869
  * Either:
4952
- * - a `StorageLocationType` (e.g. `'backups'`) → orchestrator resolves to the default of that type
4870
+ * - a `StorageLocationType` (e.g. `'backups'`) → the sole location of that type
4871
+ * (transitionally, the `<type>:default`-slugged row when several exist)
4953
4872
  * - a fully-qualified id (e.g. `'backups:nas-01'`) → addresses a specific instance
4954
4873
  *
4955
4874
  * The orchestrator's `resolveRef(ref)` handles both cases.
@@ -5131,6 +5050,111 @@ var DecoderSessionConfigSchema = z.object({
5131
5050
  */
5132
5051
  debug: z.boolean().optional()
5133
5052
  });
5053
+ /**
5054
+ * Per-component log CHANNELS — the gate a hot path consults, and the registry
5055
+ * an addon declares its channels in.
5056
+ *
5057
+ * ## Two axes, deliberately separated
5058
+ *
5059
+ * - **DECLARATION** — which channels exist. Only the addon knows:
5060
+ * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
5061
+ * baichuan/handshake. A hand-wired central list rots at the first addition,
5062
+ * and rots silently. So a channel is declared where it is consulted, and the
5063
+ * `log-channels` capability enumerates the declarations.
5064
+ * - **VALUE** — at which level, for which scope, until when. That stays ONE
5065
+ * thing: the logging settings document on the `system` cap. Two authorities
5066
+ * over the values is the exact defect
5067
+ * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
5068
+ * remove; re-introducing it from the cure side would be grotesque.
5069
+ *
5070
+ * Nothing in this file reads a clock, an env var or a store. The registry is
5071
+ * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
5072
+ * the hot path with a value somebody actually read, and by
5073
+ * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
5074
+ * never reaches here, so it can neither disarm an armed channel nor arm a
5075
+ * disarmed one (D49).
5076
+ *
5077
+ * ## The canonical call shape
5078
+ *
5079
+ * ```ts
5080
+ * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
5081
+ * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
5082
+ * }
5083
+ * ```
5084
+ *
5085
+ * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
5086
+ * read. Disarmed, a call site costs one load and one branch, and the `extras`
5087
+ * object literal is never constructed because it lives inside the branch. It
5088
+ * is the same shape already proven in production at `stream-broker.ts:1650`,
5089
+ * and the same discipline `LoggingGate.allowsDestination` uses for the
5090
+ * destination floor (measured at 1.93 ns/call when off).
5091
+ *
5092
+ * ## Why a channel emits at `info`
5093
+ *
5094
+ * `loki-logging.addon.ts` pins the destination default at `info` and
5095
+ * `loki-destination.ts` drops everything below it, so a line emitted at
5096
+ * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
5097
+ * minutes. A diagnostic that cannot be read an hour later is worse than no
5098
+ * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
5099
+ * emits at the channel's declared level, whose schema floor is `info`.
5100
+ */
5101
+ /**
5102
+ * The level a channel writes at once armed.
5103
+ *
5104
+ * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
5105
+ * not leave the process for Loki, and the whole point of arming a channel is
5106
+ * to read it later.
5107
+ */
5108
+ var LogChannelLevelSchema = z.enum([
5109
+ "info",
5110
+ "warn",
5111
+ "error"
5112
+ ]);
5113
+ /**
5114
+ * What an addon declares about one channel. No value, no state — a
5115
+ * declaration is inert.
5116
+ */
5117
+ var LogChannelDescriptorSchema = z.object({
5118
+ /**
5119
+ * Dotted `area.thing`, unique across the workspace. `area` is conventionally
5120
+ * the addon's short name so an operator reading a channel list can tell who
5121
+ * owns it without a second lookup.
5122
+ */
5123
+ name: z.string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
5124
+ /** One sentence: what the operator will SEE after arming it. */
5125
+ description: z.string().min(1),
5126
+ /** The level its lines are emitted at. Never below `info`. */
5127
+ defaultLevel: LogChannelLevelSchema,
5128
+ /**
5129
+ * Whether this channel can be narrowed to a camera.
5130
+ *
5131
+ * `true` is a PROMISE with two halves, and both must hold: the gate is
5132
+ * consulted with the numeric device id, AND every line the channel admits
5133
+ * carries `tags: { deviceId }` with that same numeric id. The second half is
5134
+ * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
5135
+ * keeps `deviceId` out of the stream labels for cardinality, so the tag in
5136
+ * the body is the only way to filter.
5137
+ *
5138
+ * A channel whose lines carry the device only in `meta` (or not at all) is
5139
+ * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
5140
+ * the operator narrows to one camera, sees nothing, and concludes the code
5141
+ * path was never taken.
5142
+ */
5143
+ perDevice: z.boolean()
5144
+ });
5145
+ /**
5146
+ * An armed window over one channel, as the document hands it to a mirror.
5147
+ *
5148
+ * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
5149
+ * expires by itself, which is the one failure a boolean cannot avoid.
5150
+ */
5151
+ var LogChannelWindowSchema = z.object({
5152
+ channel: z.string().min(1),
5153
+ /** Epoch ms the window closes at. */
5154
+ armedUntilMs: z.number(),
5155
+ /** `null` = every camera. A non-empty list narrows to those numeric ids. */
5156
+ deviceIds: z.array(z.number().int()).readonly().nullable()
5157
+ });
5134
5158
  /** Bucket key for rows no addon owns. Stable, so its series is continuous. */
5135
5159
  var UNATTRIBUTED_BUCKET_KEY = "__unattributed__";
5136
5160
  var ROOT_BUCKET_KEY = "__root__";
@@ -7186,12 +7210,30 @@ var BackupDestinationInfoSchema = z.object({
7186
7210
  lastSuccessAt: z.number().optional(),
7187
7211
  /** Newest-archive size from `manifests.json`, or undefined. */
7188
7212
  lastSuccessSizeBytes: z.number().optional(),
7189
- /** Per-destination cron expression. Empty = manual-only (no schedule). */
7213
+ /**
7214
+ * Cron cadence(s) of the ENABLED schedules that fan out to this
7215
+ * destination, comma-joined. Absent when no enabled schedule targets it
7216
+ * — a destination nothing is scheduled to write to must not advertise a
7217
+ * cadence (D384). This is never the `backup_destination_policies.cron`
7218
+ * column: that per-location cron has scheduled nothing since 2026-07-28
7219
+ * and reading it made a destination with a DISABLED schedule claim a
7220
+ * nightly run.
7221
+ */
7190
7222
  cron: z.string().optional(),
7191
- /** ms-epoch of next computed firing for this destination's cron, if any. */
7223
+ /** ms-epoch of the next firing across those schedules (earliest), if any. */
7192
7224
  nextRunAt: z.number().optional(),
7193
- /** ms-epoch of last successful scheduled run (mirrors policy.lastRunAt). */
7194
- lastRunAt: z.number().optional()
7225
+ /**
7226
+ * ms-epoch of the last time a run ATTEMPTED to write here — success or
7227
+ * failure. Never a success stamp: pair it with `lastSuccessAt` (the
7228
+ * newest archive that actually landed) and `lastError`.
7229
+ */
7230
+ lastAttemptAt: z.number().optional(),
7231
+ /**
7232
+ * Why the last attempt failed, verbatim. Absent when the last attempt
7233
+ * landed the archive. A destination that has never been written to has
7234
+ * neither this nor `lastAttemptAt`.
7235
+ */
7236
+ lastError: z.string().optional()
7195
7237
  });
7196
7238
  /**
7197
7239
  * Per-archive entry returned by `backup.listArchives({ destinationId })`.
@@ -7354,8 +7396,16 @@ var BackupScheduleSchema = z.object({
7354
7396
  retentionCount: z.number().int().min(1).max(1e3),
7355
7397
  /** Optional subset of source locations to include; omitted = all. */
7356
7398
  dataSources: z.array(z.string()).readonly().optional(),
7357
- /** ms-epoch of last successful run. */
7358
- lastRunAt: z.number().optional(),
7399
+ /**
7400
+ * ms-epoch of the last tick that FIRED this schedule. Stamped before the
7401
+ * archive runs (it is the dedupe anchor), so it says "attempted", never
7402
+ * "succeeded" — a run refused by every destination stamps it too.
7403
+ */
7404
+ lastAttemptAt: z.number().optional(),
7405
+ /** ms-epoch of the last run of this schedule that landed at ≥1 destination. */
7406
+ lastSuccessAt: z.number().optional(),
7407
+ /** Why the last fired run failed, verbatim. Absent when it succeeded. */
7408
+ lastError: z.string().optional(),
7359
7409
  /** ms-epoch of next computed firing (read-only, filled on list). */
7360
7410
  nextRunAt: z.number().optional()
7361
7411
  });
@@ -7484,14 +7534,7 @@ var backupCapability = {
7484
7534
  locationId: z.string(),
7485
7535
  enabled: z.boolean(),
7486
7536
  retentionCount: z.number().int().min(1).max(1e3),
7487
- label: z.string().optional(),
7488
- /**
7489
- * Per-destination cron expression. Empty string clears the
7490
- * schedule (manual-only). Validated server-side via croner;
7491
- * malformed expressions reject the upsert with an actionable
7492
- * message.
7493
- */
7494
- cron: z.string().optional()
7537
+ label: z.string().optional()
7495
7538
  }), z.void(), {
7496
7539
  kind: "mutation",
7497
7540
  auth: "admin"
@@ -22071,7 +22114,6 @@ var storageCapability = {
22071
22114
  }), z.instanceof(Uint8Array)),
22072
22115
  endDownload: method(z.object({ downloadId: z.string() }), z.void(), { kind: "mutation" }),
22073
22116
  listLocations: method(z.object({ type: StorageLocationTypeSchema.optional() }), z.array(StorageLocationSchema).readonly()),
22074
- getDefaultLocation: method(z.object({ type: StorageLocationTypeSchema }), StorageLocationSchema.nullable()),
22075
22117
  listLocationDeclarations: method(z.void(), z.array(StorageLocationDeclarationSchema).readonly()),
22076
22118
  upsertLocation: method(StorageLocationSchema.omit({
22077
22119
  createdAt: true,
@@ -34590,6 +34632,63 @@ var RUNTIME_DEFAULTS = {
34590
34632
  "auth.tokenExpiry": "30d"
34591
34633
  };
34592
34634
  /**
34635
+ * Accessory device helpers — shared across drivers.
34636
+ *
34637
+ * Many vendor-specific drivers register accessory child devices on
34638
+ * top of a parent (Reolink: siren / floodlight / PIR / autotrack /
34639
+ * chime; ONVIF: relay outputs; future: Tapo Hub child devices). Each
34640
+ * driver picks the right `DeviceType` + `DeviceRole` explicitly when
34641
+ * spawning, builds a name derived from the parent, and produces a
34642
+ * stableId tied to the parent so boot-restore can reconstruct the
34643
+ * relationship.
34644
+ *
34645
+ * Centralised `(kind → DeviceType)` mapping was dropped on purpose:
34646
+ * drivers may reasonably disagree on the right type for an accessory
34647
+ * (a Reolink PIR exposes a switch on/off + sensitivity, while a hypothetical
34648
+ * read-only motion-only sensor might be `DeviceType.Sensor`). Forcing
34649
+ * one canonical mapping was over-prescriptive and added a layer of
34650
+ * indirection without saving meaningful code at call sites — the
34651
+ * driver knows its own hardware best.
34652
+ */
34653
+ /**
34654
+ * Subset of `DeviceRole` values that drivers register as child
34655
+ * accessories of a parent device. Sourced verbatim from `DeviceRole`
34656
+ * — `AccessoryKind` is the alias drivers use when building accessory
34657
+ * children, so the call site reads as
34658
+ * `accessoryStableId(parent, AccessoryKind.Siren)` rather than
34659
+ * `accessoryStableId(parent, DeviceRole.Siren)` (which would imply
34660
+ * any role works, including non-accessory ones like Doorbell).
34661
+ */
34662
+ var AccessoryKind = {
34663
+ Siren: DeviceRole.Siren,
34664
+ Floodlight: DeviceRole.Floodlight,
34665
+ Spotlight: DeviceRole.Spotlight,
34666
+ PirSensor: DeviceRole.PirSensor,
34667
+ Chime: DeviceRole.Chime,
34668
+ Autotrack: DeviceRole.Autotrack,
34669
+ Nightvision: DeviceRole.Nightvision,
34670
+ PrivacyMask: DeviceRole.PrivacyMask
34671
+ };
34672
+ AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
34673
+ /**
34674
+ * THE derivation. One crop rectangle, one presence verdict — see D52 for why
34675
+ * this repo insists a derived value has exactly one implementation.
34676
+ *
34677
+ * `undefined` status ⇒ `sleeping`. A device with no slice has made no claim,
34678
+ * and the caller decides separately whether it is even battery-operated
34679
+ * (`DeviceFeature.BatteryOperated`); this function never answers that
34680
+ * question, only what a battery device is doing.
34681
+ */
34682
+ function deriveBatteryPresence(input) {
34683
+ const status = input.status;
34684
+ if (!status) return "sleeping";
34685
+ if (status.sleeping !== true) return "awake";
34686
+ const lastContactAt = status.lastContactAt;
34687
+ if (typeof lastContactAt !== "number" || lastContactAt <= 0) return "sleeping";
34688
+ const budget = input.unreachableAfterMs ?? 216e5;
34689
+ return input.nowMs - lastContactAt > budget ? "unreachable" : "sleeping";
34690
+ }
34691
+ /**
34593
34692
  * WHICH child a container stands for — one definition, for every consumer.
34594
34693
  *
34595
34694
  * A CONTAINER device has no controllable surface of its own: it groups entity
@@ -34715,63 +34814,6 @@ function resolveContainerPrimaryChild(children, overrideEntityId, containerName)
34715
34814
  const namesake = (c) => containerName !== void 0 && containerName.length > 0 && c.name !== void 0 && c.name.toLowerCase() === containerName.toLowerCase() ? 0 : 1;
34716
34815
  return [...children].toSorted((a, b) => roleRank(a.role) - roleRank(b.role) || namesake(a) - namesake(b) || rank(a.type) - rank(b.type))[0] ?? null;
34717
34816
  }
34718
- /**
34719
- * Accessory device helpers — shared across drivers.
34720
- *
34721
- * Many vendor-specific drivers register accessory child devices on
34722
- * top of a parent (Reolink: siren / floodlight / PIR / autotrack /
34723
- * chime; ONVIF: relay outputs; future: Tapo Hub child devices). Each
34724
- * driver picks the right `DeviceType` + `DeviceRole` explicitly when
34725
- * spawning, builds a name derived from the parent, and produces a
34726
- * stableId tied to the parent so boot-restore can reconstruct the
34727
- * relationship.
34728
- *
34729
- * Centralised `(kind → DeviceType)` mapping was dropped on purpose:
34730
- * drivers may reasonably disagree on the right type for an accessory
34731
- * (a Reolink PIR exposes a switch on/off + sensitivity, while a hypothetical
34732
- * read-only motion-only sensor might be `DeviceType.Sensor`). Forcing
34733
- * one canonical mapping was over-prescriptive and added a layer of
34734
- * indirection without saving meaningful code at call sites — the
34735
- * driver knows its own hardware best.
34736
- */
34737
- /**
34738
- * Subset of `DeviceRole` values that drivers register as child
34739
- * accessories of a parent device. Sourced verbatim from `DeviceRole`
34740
- * — `AccessoryKind` is the alias drivers use when building accessory
34741
- * children, so the call site reads as
34742
- * `accessoryStableId(parent, AccessoryKind.Siren)` rather than
34743
- * `accessoryStableId(parent, DeviceRole.Siren)` (which would imply
34744
- * any role works, including non-accessory ones like Doorbell).
34745
- */
34746
- var AccessoryKind = {
34747
- Siren: DeviceRole.Siren,
34748
- Floodlight: DeviceRole.Floodlight,
34749
- Spotlight: DeviceRole.Spotlight,
34750
- PirSensor: DeviceRole.PirSensor,
34751
- Chime: DeviceRole.Chime,
34752
- Autotrack: DeviceRole.Autotrack,
34753
- Nightvision: DeviceRole.Nightvision,
34754
- PrivacyMask: DeviceRole.PrivacyMask
34755
- };
34756
- AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
34757
- /**
34758
- * THE derivation. One crop rectangle, one presence verdict — see D52 for why
34759
- * this repo insists a derived value has exactly one implementation.
34760
- *
34761
- * `undefined` status ⇒ `sleeping`. A device with no slice has made no claim,
34762
- * and the caller decides separately whether it is even battery-operated
34763
- * (`DeviceFeature.BatteryOperated`); this function never answers that
34764
- * question, only what a battery device is doing.
34765
- */
34766
- function deriveBatteryPresence(input) {
34767
- const status = input.status;
34768
- if (!status) return "sleeping";
34769
- if (status.sleeping !== true) return "awake";
34770
- const lastContactAt = status.lastContactAt;
34771
- if (typeof lastContactAt !== "number" || lastContactAt <= 0) return "sleeping";
34772
- const budget = input.unreachableAfterMs ?? 216e5;
34773
- return input.nowMs - lastContactAt > budget ? "unreachable" : "sleeping";
34774
- }
34775
34817
  /** Marker written to a declared integration's `info`. */
34776
34818
  var DECLARED_INTEGRATION_FIXED_KEY = "fixed";
34777
34819
  /**
@@ -40250,12 +40292,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
40250
40292
  addonId: null,
40251
40293
  access: "view"
40252
40294
  },
40253
- "storage.getDefaultLocation": {
40254
- capName: "storage",
40255
- capScope: "system",
40256
- addonId: null,
40257
- access: "view"
40258
- },
40259
40295
  "storage.list": {
40260
40296
  capName: "storage",
40261
40297
  capScope: "system",
@@ -44246,4 +44282,4 @@ function enumerateInferenceDevices(hw) {
44246
44282
  return out;
44247
44283
  }
44248
44284
  //#endregion
44249
- export { foldSnapshotByFunction as $, hydrateSchema as $t, alertsCapability as A, storageProviderCapability as At, dataStoreProviderCapability as B, DeviceFeature as Bt, StorageCleanupJobSchema as C, scopesAllowAddon as Ct, addonPagesCapability as D, snapshotCapability as Dt, UserRecordSchema as E, settingsStoreCapability as Et, buildStreamParamsConfigSchema as F, errMsg as Ft, deviceStatusCapability as G, WELL_KNOWN_TAB_MAP as Gt, deriveBatteryPresence as H, DeviceType as Ht, collectSecretConfigKeys as I, BaseAddon as It, enumerateItemArrayFields as J, asString as Jt, doorbellCapability as K, asJsonObject as Kt, coreBlockAddonId as L, DATAPLANE_SECRET_HEADER as Lt, backupCapability as M, userManagementCapability as Mt, bareAddonId as N, vectorDimFromBase64 as Nt, addonSettingsCapability as O, storageCapability as Ot, batteryCapability as P, vectorStoreCapability as Pt, filesystemBrowseCapability as Q, expandCapMethods as Qt, coreBlockIdFromAddonId as R, DEVICE_SETTINGS_CONTRIBUTION_METHODS as Rt, ScopedTokenSchema as S, runtimeStatePolicyFor as St, StorageMigrationJobSchema as T, scoreRuntimes as Tt, deviceManagerCapability as U, ReadinessRegistry as Ut, decodeVectorBase64 as V, DeviceRole as Vt, deviceStateCapability as W, ReadinessTimeoutError as Wt, evaluateSensorEdge as X, emitDownForOwnedCaps as Xt, enumerateSchemaFields as Y, createEvent as Yt, extractNestedAddonId as Z, emitReadiness as Zt, RecordingStatusSchema as _, procedureAuthKey as _t, CAMERA_SWITCH_ORDER as a, resolveCapMount as an, isVoidInput as at, STORAGE_ACCESS_FALLBACK as b, resolveContainerPrimaryChild as bt, CORE_BLOCK_ADDON_PREFIX as c, EventCategory as cn, localNetworkCapability as ct, DeclaredDevices as d, looseSchema as dt, isDeviceConfigCap as en, isArrayOutputSchema as et, DeviceStatusSchema as f, metricsProviderCapability as ft, RUNTIME_DEFAULTS as g, platformProbeCapability as gt, REDACTED_SECRET as h, parseStreamParamsFormPatch as ht, BatteryStatusSchema as i, readinessKey as in, isSourceCap as it, authProviderCapability as j, streamQualityLabel as jt, addonWidgetsCapability as k, storageMigrationCapability as kt, CoreBlockSchema as l, logDestinationCapability as lt, METHOD_ACCESS_MAP as m, objectInputDeclaresAddonId as mt, AlertSchema as n, parseJsonObject as nn, isObjectInput as nt, CAP_NAMES_WITH_STATUS as o, scopeKey as on, kebabToCamel as ot, LOG_LEVEL_RANK as p, normalizeUnit as pt, enumerateInferenceDevices as q, asNumber as qt, ApiKeyRecordSchema as r, parseJsonUnknown as rn, isSameAddonId as rt, CORE_BLOCKS_ADDON_ID as s, sleep as sn, lifecycleJobSchema as st, ALL_CAPABILITY_DEFINITIONS as t, nodePin as tn, isCollectionArrayMethod as tt, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as u, logLevelAtMost as ut, SOURCE_CAPS as v, reducePoints as vt, StorageLocationTypeSchema as w, scopesAllowDeviceCap as wt, STREAM_PROFILE_META as x, resolveMethodAuth as xt, SOURCE_DEVICE_TYPES as y, resolveBucketMs as yt, coreBlocksCapability as z, DEVICE_STATUS_METHOD as zt };
44285
+ export { filesystemBrowseCapability as $, emitReadiness as $t, addonWidgetsCapability as A, storageCapability as At, coreBlocksCapability as B, DEVICE_SETTINGS_CONTRIBUTION_METHODS as Bt, ScopedTokenSchema as C, resolveMethodAuth as Ct, UserRecordSchema as D, scoreRuntimes as Dt, StorageMigrationJobSchema as E, scopesAllowDeviceCap as Et, batteryCapability as F, vectorDimFromBase64 as Ft, deviceStateCapability as G, ReadinessRegistry as Gt, decodeVectorBase64 as H, DeviceFeature as Ht, buildStreamParamsConfigSchema as I, vectorStoreCapability as It, enumerateInferenceDevices as J, asJsonObject as Jt, deviceStatusCapability as K, ReadinessTimeoutError as Kt, collectSecretConfigKeys as L, errMsg as Lt, authProviderCapability as M, storageProviderCapability as Mt, backupCapability as N, streamQualityLabel as Nt, addonPagesCapability as O, settingsStoreCapability as Ot, bareAddonId as P, userManagementCapability as Pt, extractNestedAddonId as Q, emitDownForOwnedCaps as Qt, coreBlockAddonId as R, BaseAddon as Rt, STREAM_PROFILE_META as S, resolveContainerPrimaryChild as St, StorageLocationTypeSchema as T, scopesAllowAddon as Tt, deriveBatteryPresence as U, DeviceRole as Ut, dataStoreProviderCapability as V, DEVICE_STATUS_METHOD as Vt, deviceManagerCapability as W, DeviceType as Wt, enumerateSchemaFields as X, asString as Xt, enumerateItemArrayFields as Y, asNumber as Yt, evaluateSensorEdge as Z, createEvent as Zt, RUNTIME_DEFAULTS as _, parseStreamParamsFormPatch as _t, CAMERA_SWITCH_ORDER as a, parseJsonUnknown as an, isSameAddonId as at, SOURCE_DEVICE_TYPES as b, reducePoints as bt, CORE_BLOCK_ADDON_PREFIX as c, scopeKey as cn, kebabToCamel as ct, DeclaredDevices as d, logDestinationCapability as dt, expandCapMethods as en, foldSnapshotByFunction as et, DeviceStatusSchema as f, logLevelAtMost as ft, REDACTED_SECRET as g, objectInputDeclaresAddonId as gt, METHOD_ACCESS_MAP as h, normalizeUnit as ht, BatteryStatusSchema as i, parseJsonObject as in, isObjectInput as it, alertsCapability as j, storageMigrationCapability as jt, addonSettingsCapability as k, snapshotCapability as kt, CoreBlockSchema as l, sleep as ln, lifecycleJobSchema as lt, LegacyStorageLocationDefaultSchema as m, metricsProviderCapability as mt, AlertSchema as n, isDeviceConfigCap as nn, isCollectionArrayMethod as nt, CAP_NAMES_WITH_STATUS as o, readinessKey as on, isSourceCap as ot, LOG_LEVEL_RANK as p, looseSchema as pt, doorbellCapability as q, WELL_KNOWN_TAB_MAP as qt, ApiKeyRecordSchema as r, nodePin as rn, isLocationEnabled as rt, CORE_BLOCKS_ADDON_ID as s, resolveCapMount as sn, isVoidInput as st, ALL_CAPABILITY_DEFINITIONS as t, hydrateSchema as tn, isArrayOutputSchema as tt, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as u, EventCategory as un, localNetworkCapability as ut, RecordingStatusSchema as v, platformProbeCapability as vt, StorageCleanupJobSchema as w, runtimeStatePolicyFor as wt, STORAGE_ACCESS_FALLBACK as x, resolveBucketMs as xt, SOURCE_CAPS as y, procedureAuthKey as yt, coreBlockIdFromAddonId as z, DATAPLANE_SECRET_HEADER as zt };