@camstack/addon-remote-storage 1.2.77 → 1.2.78

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/s3.addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-DW6PfRB-.js");
5
+ const require_shared = require("./shared-D7aelvq0.js");
6
6
  let node_stream = require("node:stream");
7
7
  let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
8
8
  let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
package/dist/s3.addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-NUBj0w5N.mjs";
1
+ import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-C5_1Zy4l.mjs";
2
2
  import { PassThrough } from "node:stream";
3
3
  import { DeleteObjectCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
4
4
  import { Upload } from "@aws-sdk/lib-storage";
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-DW6PfRB-.js");
5
+ const require_shared = require("./shared-D7aelvq0.js");
6
6
  let ssh2 = require("ssh2");
7
7
  let node_path = require("node:path");
8
8
  node_path = require_shared.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-NUBj0w5N.mjs";
1
+ import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-C5_1Zy4l.mjs";
2
2
  import { Client } from "ssh2";
3
3
  import * as path from "node:path";
4
4
  //#region src/providers/sftp/sftp-config-schema.ts
@@ -7600,111 +7600,6 @@ var CameraSwitchGroupSchema = object({
7600
7600
  fetchedAt: number()
7601
7601
  });
7602
7602
  /**
7603
- * Per-component log CHANNELS — the gate a hot path consults, and the registry
7604
- * an addon declares its channels in.
7605
- *
7606
- * ## Two axes, deliberately separated
7607
- *
7608
- * - **DECLARATION** — which channels exist. Only the addon knows:
7609
- * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
7610
- * baichuan/handshake. A hand-wired central list rots at the first addition,
7611
- * and rots silently. So a channel is declared where it is consulted, and the
7612
- * `log-channels` capability enumerates the declarations.
7613
- * - **VALUE** — at which level, for which scope, until when. That stays ONE
7614
- * thing: the logging settings document on the `system` cap. Two authorities
7615
- * over the values is the exact defect
7616
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
7617
- * remove; re-introducing it from the cure side would be grotesque.
7618
- *
7619
- * Nothing in this file reads a clock, an env var or a store. The registry is
7620
- * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
7621
- * the hot path with a value somebody actually read, and by
7622
- * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
7623
- * never reaches here, so it can neither disarm an armed channel nor arm a
7624
- * disarmed one (D49).
7625
- *
7626
- * ## The canonical call shape
7627
- *
7628
- * ```ts
7629
- * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
7630
- * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
7631
- * }
7632
- * ```
7633
- *
7634
- * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
7635
- * read. Disarmed, a call site costs one load and one branch, and the `extras`
7636
- * object literal is never constructed because it lives inside the branch. It
7637
- * is the same shape already proven in production at `stream-broker.ts:1650`,
7638
- * and the same discipline `LoggingGate.allowsDestination` uses for the
7639
- * destination floor (measured at 1.93 ns/call when off).
7640
- *
7641
- * ## Why a channel emits at `info`
7642
- *
7643
- * `loki-logging.addon.ts` pins the destination default at `info` and
7644
- * `loki-destination.ts` drops everything below it, so a line emitted at
7645
- * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
7646
- * minutes. A diagnostic that cannot be read an hour later is worse than no
7647
- * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
7648
- * emits at the channel's declared level, whose schema floor is `info`.
7649
- */
7650
- /**
7651
- * The level a channel writes at once armed.
7652
- *
7653
- * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
7654
- * not leave the process for Loki, and the whole point of arming a channel is
7655
- * to read it later.
7656
- */
7657
- var LogChannelLevelSchema = _enum([
7658
- "info",
7659
- "warn",
7660
- "error"
7661
- ]);
7662
- /**
7663
- * What an addon declares about one channel. No value, no state — a
7664
- * declaration is inert.
7665
- */
7666
- var LogChannelDescriptorSchema = object({
7667
- /**
7668
- * Dotted `area.thing`, unique across the workspace. `area` is conventionally
7669
- * the addon's short name so an operator reading a channel list can tell who
7670
- * owns it without a second lookup.
7671
- */
7672
- name: string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
7673
- /** One sentence: what the operator will SEE after arming it. */
7674
- description: string().min(1),
7675
- /** The level its lines are emitted at. Never below `info`. */
7676
- defaultLevel: LogChannelLevelSchema,
7677
- /**
7678
- * Whether this channel can be narrowed to a camera.
7679
- *
7680
- * `true` is a PROMISE with two halves, and both must hold: the gate is
7681
- * consulted with the numeric device id, AND every line the channel admits
7682
- * carries `tags: { deviceId }` with that same numeric id. The second half is
7683
- * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
7684
- * keeps `deviceId` out of the stream labels for cardinality, so the tag in
7685
- * the body is the only way to filter.
7686
- *
7687
- * A channel whose lines carry the device only in `meta` (or not at all) is
7688
- * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
7689
- * the operator narrows to one camera, sees nothing, and concludes the code
7690
- * path was never taken.
7691
- */
7692
- perDevice: boolean()
7693
- });
7694
- /**
7695
- * An armed window over one channel, as the document hands it to a mirror.
7696
- *
7697
- * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
7698
- * expires by itself, which is the one failure a boolean cannot avoid.
7699
- */
7700
- var LogChannelWindowSchema = object({
7701
- channel: string().min(1),
7702
- /** Epoch ms the window closes at. */
7703
- armedUntilMs: number(),
7704
- /** `null` = every camera. A non-empty list narrows to those numeric ids. */
7705
- deviceIds: array(number().int()).readonly().nullable()
7706
- });
7707
- /**
7708
7603
  * Ops-log — the durable, append-only operations audit shared by the
7709
7604
  * recordings and events management surfaces.
7710
7605
  *
@@ -8650,8 +8545,11 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8650
8545
  * `STORAGE_LOCATION_CARDINALITY` map has been removed.
8651
8546
  *
8652
8547
  * `id` is a stable namespaced string of the form `<type>:<slug>`.
8653
- * The default location for a type uses `id === <type>:default` by
8654
- * convention (the bare type ref like `'backups'` resolves to it).
8548
+ * The seed names its first instance `<type>:default` — a NAME, not a flag.
8549
+ * There is no default location any more (D383): `enabled` is the whole write
8550
+ * model, and a bare type ref resolves to the sole location of the type, or —
8551
+ * transitionally, only while legacy NULL-stamped rows exist — to the row whose
8552
+ * slug is `default`.
8655
8553
  *
8656
8554
  * `isSystem` is a legacy persisted flag. Seed still creates the initial
8657
8555
  * `<type>:default` locations; the flag is no longer a lock, a badge, or a
@@ -8672,21 +8570,20 @@ var StorageLocationSchema = object({
8672
8570
  * flag at upsert time, not here (the schema is provider-agnostic).
8673
8571
  */
8674
8572
  nodeId: string().optional(),
8675
- isDefault: boolean().default(false),
8676
8573
  isSystem: boolean().default(false),
8677
8574
  /**
8678
- * Operator opt-in: whether consumers that BALANCE across several locations
8679
- * of a type may write here. Recordings reads it today; event media and
8680
- * backups are the next consumers, which is why the flag lives on the
8681
- * location rather than in any one addon's store nothing has to be
8682
- * extended to add the next consumer.
8575
+ * THE write switch, and the only one (D383). `enabled: true` means every
8576
+ * consumer that chooses a write target for this type may write here, and all
8577
+ * enabled locations of a type are used TOGETHER; `false` means read-only
8578
+ * still read, still played back, still age-swept, still drained, never
8579
+ * written.
8683
8580
  *
8684
- * OPTIONAL, and ABSENT MEANS ACTIVE. Every location persisted before the
8685
- * flag existed reads back with no flag and keeps working exactly as before;
8686
- * that is the whole compat story, and it is why no migration ships with it.
8687
- * A newly CREATED sibling is stamped `false` by the orchestrator (creating a
8688
- * disk must not silently start writing to it); the default of a type is
8689
- * always stamped `true`.
8581
+ * OPTIONAL only for the wire: an upsert that omits it means "leave what is
8582
+ * stored" on an update and "born inert unless it is the first location of its
8583
+ * type" on a create. On a PERSISTED row absence is legacy and it means
8584
+ * enabled {@link isLocationEnabled} is the one place that says so, and the
8585
+ * orchestrator stamps every flagless row `true` once at hydrate so absence
8586
+ * stops existing rather than being re-derived on every read.
8690
8587
  */
8691
8588
  enabled: boolean().optional(),
8692
8589
  /** COMPUTED at read time by the orchestrator (statfs of the backing volume
@@ -8699,10 +8596,12 @@ var StorageLocationSchema = object({
8699
8596
  createdAt: number(),
8700
8597
  updatedAt: number()
8701
8598
  });
8599
+ object({ isDefault: boolean().optional() });
8702
8600
  /**
8703
8601
  * Reference accepted by consumer-facing `api.storage.*` calls.
8704
8602
  * Either:
8705
- * - a `StorageLocationType` (e.g. `'backups'`) → orchestrator resolves to the default of that type
8603
+ * - a `StorageLocationType` (e.g. `'backups'`) → the sole location of that type
8604
+ * (transitionally, the `<type>:default`-slugged row when several exist)
8706
8605
  * - a fully-qualified id (e.g. `'backups:nas-01'`) → addresses a specific instance
8707
8606
  *
8708
8607
  * The orchestrator's `resolveRef(ref)` handles both cases.
@@ -8878,6 +8777,111 @@ var DecoderSessionConfigSchema = object({
8878
8777
  */
8879
8778
  debug: boolean().optional()
8880
8779
  });
8780
+ /**
8781
+ * Per-component log CHANNELS — the gate a hot path consults, and the registry
8782
+ * an addon declares its channels in.
8783
+ *
8784
+ * ## Two axes, deliberately separated
8785
+ *
8786
+ * - **DECLARATION** — which channels exist. Only the addon knows:
8787
+ * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
8788
+ * baichuan/handshake. A hand-wired central list rots at the first addition,
8789
+ * and rots silently. So a channel is declared where it is consulted, and the
8790
+ * `log-channels` capability enumerates the declarations.
8791
+ * - **VALUE** — at which level, for which scope, until when. That stays ONE
8792
+ * thing: the logging settings document on the `system` cap. Two authorities
8793
+ * over the values is the exact defect
8794
+ * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
8795
+ * remove; re-introducing it from the cure side would be grotesque.
8796
+ *
8797
+ * Nothing in this file reads a clock, an env var or a store. The registry is
8798
+ * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
8799
+ * the hot path with a value somebody actually read, and by
8800
+ * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
8801
+ * never reaches here, so it can neither disarm an armed channel nor arm a
8802
+ * disarmed one (D49).
8803
+ *
8804
+ * ## The canonical call shape
8805
+ *
8806
+ * ```ts
8807
+ * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
8808
+ * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
8809
+ * }
8810
+ * ```
8811
+ *
8812
+ * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
8813
+ * read. Disarmed, a call site costs one load and one branch, and the `extras`
8814
+ * object literal is never constructed because it lives inside the branch. It
8815
+ * is the same shape already proven in production at `stream-broker.ts:1650`,
8816
+ * and the same discipline `LoggingGate.allowsDestination` uses for the
8817
+ * destination floor (measured at 1.93 ns/call when off).
8818
+ *
8819
+ * ## Why a channel emits at `info`
8820
+ *
8821
+ * `loki-logging.addon.ts` pins the destination default at `info` and
8822
+ * `loki-destination.ts` drops everything below it, so a line emitted at
8823
+ * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
8824
+ * minutes. A diagnostic that cannot be read an hour later is worse than no
8825
+ * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
8826
+ * emits at the channel's declared level, whose schema floor is `info`.
8827
+ */
8828
+ /**
8829
+ * The level a channel writes at once armed.
8830
+ *
8831
+ * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
8832
+ * not leave the process for Loki, and the whole point of arming a channel is
8833
+ * to read it later.
8834
+ */
8835
+ var LogChannelLevelSchema = _enum([
8836
+ "info",
8837
+ "warn",
8838
+ "error"
8839
+ ]);
8840
+ /**
8841
+ * What an addon declares about one channel. No value, no state — a
8842
+ * declaration is inert.
8843
+ */
8844
+ var LogChannelDescriptorSchema = object({
8845
+ /**
8846
+ * Dotted `area.thing`, unique across the workspace. `area` is conventionally
8847
+ * the addon's short name so an operator reading a channel list can tell who
8848
+ * owns it without a second lookup.
8849
+ */
8850
+ name: string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
8851
+ /** One sentence: what the operator will SEE after arming it. */
8852
+ description: string().min(1),
8853
+ /** The level its lines are emitted at. Never below `info`. */
8854
+ defaultLevel: LogChannelLevelSchema,
8855
+ /**
8856
+ * Whether this channel can be narrowed to a camera.
8857
+ *
8858
+ * `true` is a PROMISE with two halves, and both must hold: the gate is
8859
+ * consulted with the numeric device id, AND every line the channel admits
8860
+ * carries `tags: { deviceId }` with that same numeric id. The second half is
8861
+ * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
8862
+ * keeps `deviceId` out of the stream labels for cardinality, so the tag in
8863
+ * the body is the only way to filter.
8864
+ *
8865
+ * A channel whose lines carry the device only in `meta` (or not at all) is
8866
+ * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
8867
+ * the operator narrows to one camera, sees nothing, and concludes the code
8868
+ * path was never taken.
8869
+ */
8870
+ perDevice: boolean()
8871
+ });
8872
+ /**
8873
+ * An armed window over one channel, as the document hands it to a mirror.
8874
+ *
8875
+ * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
8876
+ * expires by itself, which is the one failure a boolean cannot avoid.
8877
+ */
8878
+ var LogChannelWindowSchema = object({
8879
+ channel: string().min(1),
8880
+ /** Epoch ms the window closes at. */
8881
+ armedUntilMs: number(),
8882
+ /** `null` = every camera. A non-empty list narrows to those numeric ids. */
8883
+ deviceIds: array(number().int()).readonly().nullable()
8884
+ });
8881
8885
  var MODEL_FORMATS = [
8882
8886
  "onnx",
8883
8887
  "coreml",
@@ -21542,7 +21546,7 @@ method(object({
21542
21546
  downloadId: string(),
21543
21547
  offset: number(),
21544
21548
  length: number()
21545
- }), _instanceof(Uint8Array)), method(object({ downloadId: string() }), _void(), { kind: "mutation" }), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(object({ type: StorageLocationTypeSchema }), StorageLocationSchema.nullable()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(StorageLocationSchema.omit({
21549
+ }), _instanceof(Uint8Array)), method(object({ downloadId: string() }), _void(), { kind: "mutation" }), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(StorageLocationSchema.omit({
21546
21550
  createdAt: true,
21547
21551
  updatedAt: true
21548
21552
  }), StorageLocationSchema, {
@@ -34451,12 +34455,6 @@ Object.freeze({
34451
34455
  addonId: null,
34452
34456
  access: "view"
34453
34457
  },
34454
- "storage.getDefaultLocation": {
34455
- capName: "storage",
34456
- capScope: "system",
34457
- addonId: null,
34458
- access: "view"
34459
- },
34460
34458
  "storage.list": {
34461
34459
  capName: "storage",
34462
34460
  capScope: "system",
@@ -7623,111 +7623,6 @@ var CameraSwitchGroupSchema = object({
7623
7623
  fetchedAt: number()
7624
7624
  });
7625
7625
  /**
7626
- * Per-component log CHANNELS — the gate a hot path consults, and the registry
7627
- * an addon declares its channels in.
7628
- *
7629
- * ## Two axes, deliberately separated
7630
- *
7631
- * - **DECLARATION** — which channels exist. Only the addon knows:
7632
- * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
7633
- * baichuan/handshake. A hand-wired central list rots at the first addition,
7634
- * and rots silently. So a channel is declared where it is consulted, and the
7635
- * `log-channels` capability enumerates the declarations.
7636
- * - **VALUE** — at which level, for which scope, until when. That stays ONE
7637
- * thing: the logging settings document on the `system` cap. Two authorities
7638
- * over the values is the exact defect
7639
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
7640
- * remove; re-introducing it from the cure side would be grotesque.
7641
- *
7642
- * Nothing in this file reads a clock, an env var or a store. The registry is
7643
- * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
7644
- * the hot path with a value somebody actually read, and by
7645
- * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
7646
- * never reaches here, so it can neither disarm an armed channel nor arm a
7647
- * disarmed one (D49).
7648
- *
7649
- * ## The canonical call shape
7650
- *
7651
- * ```ts
7652
- * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
7653
- * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
7654
- * }
7655
- * ```
7656
- *
7657
- * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
7658
- * read. Disarmed, a call site costs one load and one branch, and the `extras`
7659
- * object literal is never constructed because it lives inside the branch. It
7660
- * is the same shape already proven in production at `stream-broker.ts:1650`,
7661
- * and the same discipline `LoggingGate.allowsDestination` uses for the
7662
- * destination floor (measured at 1.93 ns/call when off).
7663
- *
7664
- * ## Why a channel emits at `info`
7665
- *
7666
- * `loki-logging.addon.ts` pins the destination default at `info` and
7667
- * `loki-destination.ts` drops everything below it, so a line emitted at
7668
- * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
7669
- * minutes. A diagnostic that cannot be read an hour later is worse than no
7670
- * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
7671
- * emits at the channel's declared level, whose schema floor is `info`.
7672
- */
7673
- /**
7674
- * The level a channel writes at once armed.
7675
- *
7676
- * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
7677
- * not leave the process for Loki, and the whole point of arming a channel is
7678
- * to read it later.
7679
- */
7680
- var LogChannelLevelSchema = _enum([
7681
- "info",
7682
- "warn",
7683
- "error"
7684
- ]);
7685
- /**
7686
- * What an addon declares about one channel. No value, no state — a
7687
- * declaration is inert.
7688
- */
7689
- var LogChannelDescriptorSchema = object({
7690
- /**
7691
- * Dotted `area.thing`, unique across the workspace. `area` is conventionally
7692
- * the addon's short name so an operator reading a channel list can tell who
7693
- * owns it without a second lookup.
7694
- */
7695
- name: string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
7696
- /** One sentence: what the operator will SEE after arming it. */
7697
- description: string().min(1),
7698
- /** The level its lines are emitted at. Never below `info`. */
7699
- defaultLevel: LogChannelLevelSchema,
7700
- /**
7701
- * Whether this channel can be narrowed to a camera.
7702
- *
7703
- * `true` is a PROMISE with two halves, and both must hold: the gate is
7704
- * consulted with the numeric device id, AND every line the channel admits
7705
- * carries `tags: { deviceId }` with that same numeric id. The second half is
7706
- * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
7707
- * keeps `deviceId` out of the stream labels for cardinality, so the tag in
7708
- * the body is the only way to filter.
7709
- *
7710
- * A channel whose lines carry the device only in `meta` (or not at all) is
7711
- * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
7712
- * the operator narrows to one camera, sees nothing, and concludes the code
7713
- * path was never taken.
7714
- */
7715
- perDevice: boolean()
7716
- });
7717
- /**
7718
- * An armed window over one channel, as the document hands it to a mirror.
7719
- *
7720
- * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
7721
- * expires by itself, which is the one failure a boolean cannot avoid.
7722
- */
7723
- var LogChannelWindowSchema = object({
7724
- channel: string().min(1),
7725
- /** Epoch ms the window closes at. */
7726
- armedUntilMs: number(),
7727
- /** `null` = every camera. A non-empty list narrows to those numeric ids. */
7728
- deviceIds: array(number().int()).readonly().nullable()
7729
- });
7730
- /**
7731
7626
  * Ops-log — the durable, append-only operations audit shared by the
7732
7627
  * recordings and events management surfaces.
7733
7628
  *
@@ -8673,8 +8568,11 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8673
8568
  * `STORAGE_LOCATION_CARDINALITY` map has been removed.
8674
8569
  *
8675
8570
  * `id` is a stable namespaced string of the form `<type>:<slug>`.
8676
- * The default location for a type uses `id === <type>:default` by
8677
- * convention (the bare type ref like `'backups'` resolves to it).
8571
+ * The seed names its first instance `<type>:default` — a NAME, not a flag.
8572
+ * There is no default location any more (D383): `enabled` is the whole write
8573
+ * model, and a bare type ref resolves to the sole location of the type, or —
8574
+ * transitionally, only while legacy NULL-stamped rows exist — to the row whose
8575
+ * slug is `default`.
8678
8576
  *
8679
8577
  * `isSystem` is a legacy persisted flag. Seed still creates the initial
8680
8578
  * `<type>:default` locations; the flag is no longer a lock, a badge, or a
@@ -8695,21 +8593,20 @@ var StorageLocationSchema = object({
8695
8593
  * flag at upsert time, not here (the schema is provider-agnostic).
8696
8594
  */
8697
8595
  nodeId: string().optional(),
8698
- isDefault: boolean().default(false),
8699
8596
  isSystem: boolean().default(false),
8700
8597
  /**
8701
- * Operator opt-in: whether consumers that BALANCE across several locations
8702
- * of a type may write here. Recordings reads it today; event media and
8703
- * backups are the next consumers, which is why the flag lives on the
8704
- * location rather than in any one addon's store nothing has to be
8705
- * extended to add the next consumer.
8598
+ * THE write switch, and the only one (D383). `enabled: true` means every
8599
+ * consumer that chooses a write target for this type may write here, and all
8600
+ * enabled locations of a type are used TOGETHER; `false` means read-only
8601
+ * still read, still played back, still age-swept, still drained, never
8602
+ * written.
8706
8603
  *
8707
- * OPTIONAL, and ABSENT MEANS ACTIVE. Every location persisted before the
8708
- * flag existed reads back with no flag and keeps working exactly as before;
8709
- * that is the whole compat story, and it is why no migration ships with it.
8710
- * A newly CREATED sibling is stamped `false` by the orchestrator (creating a
8711
- * disk must not silently start writing to it); the default of a type is
8712
- * always stamped `true`.
8604
+ * OPTIONAL only for the wire: an upsert that omits it means "leave what is
8605
+ * stored" on an update and "born inert unless it is the first location of its
8606
+ * type" on a create. On a PERSISTED row absence is legacy and it means
8607
+ * enabled {@link isLocationEnabled} is the one place that says so, and the
8608
+ * orchestrator stamps every flagless row `true` once at hydrate so absence
8609
+ * stops existing rather than being re-derived on every read.
8713
8610
  */
8714
8611
  enabled: boolean().optional(),
8715
8612
  /** COMPUTED at read time by the orchestrator (statfs of the backing volume
@@ -8722,10 +8619,12 @@ var StorageLocationSchema = object({
8722
8619
  createdAt: number(),
8723
8620
  updatedAt: number()
8724
8621
  });
8622
+ object({ isDefault: boolean().optional() });
8725
8623
  /**
8726
8624
  * Reference accepted by consumer-facing `api.storage.*` calls.
8727
8625
  * Either:
8728
- * - a `StorageLocationType` (e.g. `'backups'`) → orchestrator resolves to the default of that type
8626
+ * - a `StorageLocationType` (e.g. `'backups'`) → the sole location of that type
8627
+ * (transitionally, the `<type>:default`-slugged row when several exist)
8729
8628
  * - a fully-qualified id (e.g. `'backups:nas-01'`) → addresses a specific instance
8730
8629
  *
8731
8630
  * The orchestrator's `resolveRef(ref)` handles both cases.
@@ -8901,6 +8800,111 @@ var DecoderSessionConfigSchema = object({
8901
8800
  */
8902
8801
  debug: boolean().optional()
8903
8802
  });
8803
+ /**
8804
+ * Per-component log CHANNELS — the gate a hot path consults, and the registry
8805
+ * an addon declares its channels in.
8806
+ *
8807
+ * ## Two axes, deliberately separated
8808
+ *
8809
+ * - **DECLARATION** — which channels exist. Only the addon knows:
8810
+ * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
8811
+ * baichuan/handshake. A hand-wired central list rots at the first addition,
8812
+ * and rots silently. So a channel is declared where it is consulted, and the
8813
+ * `log-channels` capability enumerates the declarations.
8814
+ * - **VALUE** — at which level, for which scope, until when. That stays ONE
8815
+ * thing: the logging settings document on the `system` cap. Two authorities
8816
+ * over the values is the exact defect
8817
+ * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
8818
+ * remove; re-introducing it from the cure side would be grotesque.
8819
+ *
8820
+ * Nothing in this file reads a clock, an env var or a store. The registry is
8821
+ * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
8822
+ * the hot path with a value somebody actually read, and by
8823
+ * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
8824
+ * never reaches here, so it can neither disarm an armed channel nor arm a
8825
+ * disarmed one (D49).
8826
+ *
8827
+ * ## The canonical call shape
8828
+ *
8829
+ * ```ts
8830
+ * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
8831
+ * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
8832
+ * }
8833
+ * ```
8834
+ *
8835
+ * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
8836
+ * read. Disarmed, a call site costs one load and one branch, and the `extras`
8837
+ * object literal is never constructed because it lives inside the branch. It
8838
+ * is the same shape already proven in production at `stream-broker.ts:1650`,
8839
+ * and the same discipline `LoggingGate.allowsDestination` uses for the
8840
+ * destination floor (measured at 1.93 ns/call when off).
8841
+ *
8842
+ * ## Why a channel emits at `info`
8843
+ *
8844
+ * `loki-logging.addon.ts` pins the destination default at `info` and
8845
+ * `loki-destination.ts` drops everything below it, so a line emitted at
8846
+ * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
8847
+ * minutes. A diagnostic that cannot be read an hour later is worse than no
8848
+ * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
8849
+ * emits at the channel's declared level, whose schema floor is `info`.
8850
+ */
8851
+ /**
8852
+ * The level a channel writes at once armed.
8853
+ *
8854
+ * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
8855
+ * not leave the process for Loki, and the whole point of arming a channel is
8856
+ * to read it later.
8857
+ */
8858
+ var LogChannelLevelSchema = _enum([
8859
+ "info",
8860
+ "warn",
8861
+ "error"
8862
+ ]);
8863
+ /**
8864
+ * What an addon declares about one channel. No value, no state — a
8865
+ * declaration is inert.
8866
+ */
8867
+ var LogChannelDescriptorSchema = object({
8868
+ /**
8869
+ * Dotted `area.thing`, unique across the workspace. `area` is conventionally
8870
+ * the addon's short name so an operator reading a channel list can tell who
8871
+ * owns it without a second lookup.
8872
+ */
8873
+ name: string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
8874
+ /** One sentence: what the operator will SEE after arming it. */
8875
+ description: string().min(1),
8876
+ /** The level its lines are emitted at. Never below `info`. */
8877
+ defaultLevel: LogChannelLevelSchema,
8878
+ /**
8879
+ * Whether this channel can be narrowed to a camera.
8880
+ *
8881
+ * `true` is a PROMISE with two halves, and both must hold: the gate is
8882
+ * consulted with the numeric device id, AND every line the channel admits
8883
+ * carries `tags: { deviceId }` with that same numeric id. The second half is
8884
+ * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
8885
+ * keeps `deviceId` out of the stream labels for cardinality, so the tag in
8886
+ * the body is the only way to filter.
8887
+ *
8888
+ * A channel whose lines carry the device only in `meta` (or not at all) is
8889
+ * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
8890
+ * the operator narrows to one camera, sees nothing, and concludes the code
8891
+ * path was never taken.
8892
+ */
8893
+ perDevice: boolean()
8894
+ });
8895
+ /**
8896
+ * An armed window over one channel, as the document hands it to a mirror.
8897
+ *
8898
+ * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
8899
+ * expires by itself, which is the one failure a boolean cannot avoid.
8900
+ */
8901
+ var LogChannelWindowSchema = object({
8902
+ channel: string().min(1),
8903
+ /** Epoch ms the window closes at. */
8904
+ armedUntilMs: number(),
8905
+ /** `null` = every camera. A non-empty list narrows to those numeric ids. */
8906
+ deviceIds: array(number().int()).readonly().nullable()
8907
+ });
8904
8908
  var MODEL_FORMATS = [
8905
8909
  "onnx",
8906
8910
  "coreml",
@@ -21565,7 +21569,7 @@ method(object({
21565
21569
  downloadId: string(),
21566
21570
  offset: number(),
21567
21571
  length: number()
21568
- }), _instanceof(Uint8Array)), method(object({ downloadId: string() }), _void(), { kind: "mutation" }), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(object({ type: StorageLocationTypeSchema }), StorageLocationSchema.nullable()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(StorageLocationSchema.omit({
21572
+ }), _instanceof(Uint8Array)), method(object({ downloadId: string() }), _void(), { kind: "mutation" }), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(StorageLocationSchema.omit({
21569
21573
  createdAt: true,
21570
21574
  updatedAt: true
21571
21575
  }), StorageLocationSchema, {
@@ -34474,12 +34478,6 @@ Object.freeze({
34474
34478
  addonId: null,
34475
34479
  access: "view"
34476
34480
  },
34477
- "storage.getDefaultLocation": {
34478
- capName: "storage",
34479
- capScope: "system",
34480
- addonId: null,
34481
- access: "view"
34482
- },
34483
34481
  "storage.list": {
34484
34482
  capName: "storage",
34485
34483
  capScope: "system",
package/dist/smb.addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-DW6PfRB-.js");
5
+ const require_shared = require("./shared-D7aelvq0.js");
6
6
  let node_crypto = require("node:crypto");
7
7
  let node_path = require("node:path");
8
8
  node_path = require_shared.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-NUBj0w5N.mjs";
1
+ import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-C5_1Zy4l.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import * as path from "node:path";
4
4
  import * as fsp from "node:fs/promises";
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-DW6PfRB-.js");
5
+ const require_shared = require("./shared-D7aelvq0.js");
6
6
  let node_stream = require("node:stream");
7
7
  let webdav = require("webdav");
8
8
  //#region src/providers/webdav/webdav-config-schema.ts
@@ -1,4 +1,4 @@
1
- import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-NUBj0w5N.mjs";
1
+ import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-C5_1Zy4l.mjs";
2
2
  import { PassThrough } from "node:stream";
3
3
  import { AuthType, createClient } from "webdav";
4
4
  //#region src/providers/webdav/webdav-config-schema.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-remote-storage",
3
- "version": "1.2.77",
3
+ "version": "1.2.78",
4
4
  "description": "Remote storage providers (SFTP, S3, WebDAV, SMB) — unifies remote backends behind the storage-provider cap",
5
5
  "keywords": [
6
6
  "camstack",