@camstack/addon-provider-petkit 0.2.78 → 0.2.79

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 (3) hide show
  1. package/dist/addon.js +125 -127
  2. package/dist/addon.mjs +125 -127
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -8717,111 +8717,6 @@ var CameraSwitchGroupSchema = object({
8717
8717
  fetchedAt: number()
8718
8718
  });
8719
8719
  /**
8720
- * Per-component log CHANNELS — the gate a hot path consults, and the registry
8721
- * an addon declares its channels in.
8722
- *
8723
- * ## Two axes, deliberately separated
8724
- *
8725
- * - **DECLARATION** — which channels exist. Only the addon knows:
8726
- * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
8727
- * baichuan/handshake. A hand-wired central list rots at the first addition,
8728
- * and rots silently. So a channel is declared where it is consulted, and the
8729
- * `log-channels` capability enumerates the declarations.
8730
- * - **VALUE** — at which level, for which scope, until when. That stays ONE
8731
- * thing: the logging settings document on the `system` cap. Two authorities
8732
- * over the values is the exact defect
8733
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
8734
- * remove; re-introducing it from the cure side would be grotesque.
8735
- *
8736
- * Nothing in this file reads a clock, an env var or a store. The registry is
8737
- * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
8738
- * the hot path with a value somebody actually read, and by
8739
- * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
8740
- * never reaches here, so it can neither disarm an armed channel nor arm a
8741
- * disarmed one (D49).
8742
- *
8743
- * ## The canonical call shape
8744
- *
8745
- * ```ts
8746
- * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
8747
- * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
8748
- * }
8749
- * ```
8750
- *
8751
- * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
8752
- * read. Disarmed, a call site costs one load and one branch, and the `extras`
8753
- * object literal is never constructed because it lives inside the branch. It
8754
- * is the same shape already proven in production at `stream-broker.ts:1650`,
8755
- * and the same discipline `LoggingGate.allowsDestination` uses for the
8756
- * destination floor (measured at 1.93 ns/call when off).
8757
- *
8758
- * ## Why a channel emits at `info`
8759
- *
8760
- * `loki-logging.addon.ts` pins the destination default at `info` and
8761
- * `loki-destination.ts` drops everything below it, so a line emitted at
8762
- * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
8763
- * minutes. A diagnostic that cannot be read an hour later is worse than no
8764
- * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
8765
- * emits at the channel's declared level, whose schema floor is `info`.
8766
- */
8767
- /**
8768
- * The level a channel writes at once armed.
8769
- *
8770
- * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
8771
- * not leave the process for Loki, and the whole point of arming a channel is
8772
- * to read it later.
8773
- */
8774
- var LogChannelLevelSchema = _enum([
8775
- "info",
8776
- "warn",
8777
- "error"
8778
- ]);
8779
- /**
8780
- * What an addon declares about one channel. No value, no state — a
8781
- * declaration is inert.
8782
- */
8783
- var LogChannelDescriptorSchema = object({
8784
- /**
8785
- * Dotted `area.thing`, unique across the workspace. `area` is conventionally
8786
- * the addon's short name so an operator reading a channel list can tell who
8787
- * owns it without a second lookup.
8788
- */
8789
- name: string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
8790
- /** One sentence: what the operator will SEE after arming it. */
8791
- description: string().min(1),
8792
- /** The level its lines are emitted at. Never below `info`. */
8793
- defaultLevel: LogChannelLevelSchema,
8794
- /**
8795
- * Whether this channel can be narrowed to a camera.
8796
- *
8797
- * `true` is a PROMISE with two halves, and both must hold: the gate is
8798
- * consulted with the numeric device id, AND every line the channel admits
8799
- * carries `tags: { deviceId }` with that same numeric id. The second half is
8800
- * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
8801
- * keeps `deviceId` out of the stream labels for cardinality, so the tag in
8802
- * the body is the only way to filter.
8803
- *
8804
- * A channel whose lines carry the device only in `meta` (or not at all) is
8805
- * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
8806
- * the operator narrows to one camera, sees nothing, and concludes the code
8807
- * path was never taken.
8808
- */
8809
- perDevice: boolean()
8810
- });
8811
- /**
8812
- * An armed window over one channel, as the document hands it to a mirror.
8813
- *
8814
- * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
8815
- * expires by itself, which is the one failure a boolean cannot avoid.
8816
- */
8817
- var LogChannelWindowSchema = object({
8818
- channel: string().min(1),
8819
- /** Epoch ms the window closes at. */
8820
- armedUntilMs: number(),
8821
- /** `null` = every camera. A non-empty list narrows to those numeric ids. */
8822
- deviceIds: array(number().int()).readonly().nullable()
8823
- });
8824
- /**
8825
8720
  * Ops-log — the durable, append-only operations audit shared by the
8826
8721
  * recordings and events management surfaces.
8827
8722
  *
@@ -9767,8 +9662,11 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
9767
9662
  * `STORAGE_LOCATION_CARDINALITY` map has been removed.
9768
9663
  *
9769
9664
  * `id` is a stable namespaced string of the form `<type>:<slug>`.
9770
- * The default location for a type uses `id === <type>:default` by
9771
- * convention (the bare type ref like `'backups'` resolves to it).
9665
+ * The seed names its first instance `<type>:default` — a NAME, not a flag.
9666
+ * There is no default location any more (D383): `enabled` is the whole write
9667
+ * model, and a bare type ref resolves to the sole location of the type, or —
9668
+ * transitionally, only while legacy NULL-stamped rows exist — to the row whose
9669
+ * slug is `default`.
9772
9670
  *
9773
9671
  * `isSystem` is a legacy persisted flag. Seed still creates the initial
9774
9672
  * `<type>:default` locations; the flag is no longer a lock, a badge, or a
@@ -9789,21 +9687,20 @@ var StorageLocationSchema = object({
9789
9687
  * flag at upsert time, not here (the schema is provider-agnostic).
9790
9688
  */
9791
9689
  nodeId: string().optional(),
9792
- isDefault: boolean().default(false),
9793
9690
  isSystem: boolean().default(false),
9794
9691
  /**
9795
- * Operator opt-in: whether consumers that BALANCE across several locations
9796
- * of a type may write here. Recordings reads it today; event media and
9797
- * backups are the next consumers, which is why the flag lives on the
9798
- * location rather than in any one addon's store nothing has to be
9799
- * extended to add the next consumer.
9692
+ * THE write switch, and the only one (D383). `enabled: true` means every
9693
+ * consumer that chooses a write target for this type may write here, and all
9694
+ * enabled locations of a type are used TOGETHER; `false` means read-only
9695
+ * still read, still played back, still age-swept, still drained, never
9696
+ * written.
9800
9697
  *
9801
- * OPTIONAL, and ABSENT MEANS ACTIVE. Every location persisted before the
9802
- * flag existed reads back with no flag and keeps working exactly as before;
9803
- * that is the whole compat story, and it is why no migration ships with it.
9804
- * A newly CREATED sibling is stamped `false` by the orchestrator (creating a
9805
- * disk must not silently start writing to it); the default of a type is
9806
- * always stamped `true`.
9698
+ * OPTIONAL only for the wire: an upsert that omits it means "leave what is
9699
+ * stored" on an update and "born inert unless it is the first location of its
9700
+ * type" on a create. On a PERSISTED row absence is legacy and it means
9701
+ * enabled {@link isLocationEnabled} is the one place that says so, and the
9702
+ * orchestrator stamps every flagless row `true` once at hydrate so absence
9703
+ * stops existing rather than being re-derived on every read.
9807
9704
  */
9808
9705
  enabled: boolean().optional(),
9809
9706
  /** COMPUTED at read time by the orchestrator (statfs of the backing volume
@@ -9816,10 +9713,12 @@ var StorageLocationSchema = object({
9816
9713
  createdAt: number(),
9817
9714
  updatedAt: number()
9818
9715
  });
9716
+ object({ isDefault: boolean().optional() });
9819
9717
  /**
9820
9718
  * Reference accepted by consumer-facing `api.storage.*` calls.
9821
9719
  * Either:
9822
- * - a `StorageLocationType` (e.g. `'backups'`) → orchestrator resolves to the default of that type
9720
+ * - a `StorageLocationType` (e.g. `'backups'`) → the sole location of that type
9721
+ * (transitionally, the `<type>:default`-slugged row when several exist)
9823
9722
  * - a fully-qualified id (e.g. `'backups:nas-01'`) → addresses a specific instance
9824
9723
  *
9825
9724
  * The orchestrator's `resolveRef(ref)` handles both cases.
@@ -9995,6 +9894,111 @@ var DecoderSessionConfigSchema = object({
9995
9894
  */
9996
9895
  debug: boolean().optional()
9997
9896
  });
9897
+ /**
9898
+ * Per-component log CHANNELS — the gate a hot path consults, and the registry
9899
+ * an addon declares its channels in.
9900
+ *
9901
+ * ## Two axes, deliberately separated
9902
+ *
9903
+ * - **DECLARATION** — which channels exist. Only the addon knows:
9904
+ * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
9905
+ * baichuan/handshake. A hand-wired central list rots at the first addition,
9906
+ * and rots silently. So a channel is declared where it is consulted, and the
9907
+ * `log-channels` capability enumerates the declarations.
9908
+ * - **VALUE** — at which level, for which scope, until when. That stays ONE
9909
+ * thing: the logging settings document on the `system` cap. Two authorities
9910
+ * over the values is the exact defect
9911
+ * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
9912
+ * remove; re-introducing it from the cure side would be grotesque.
9913
+ *
9914
+ * Nothing in this file reads a clock, an env var or a store. The registry is
9915
+ * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
9916
+ * the hot path with a value somebody actually read, and by
9917
+ * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
9918
+ * never reaches here, so it can neither disarm an armed channel nor arm a
9919
+ * disarmed one (D49).
9920
+ *
9921
+ * ## The canonical call shape
9922
+ *
9923
+ * ```ts
9924
+ * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
9925
+ * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
9926
+ * }
9927
+ * ```
9928
+ *
9929
+ * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
9930
+ * read. Disarmed, a call site costs one load and one branch, and the `extras`
9931
+ * object literal is never constructed because it lives inside the branch. It
9932
+ * is the same shape already proven in production at `stream-broker.ts:1650`,
9933
+ * and the same discipline `LoggingGate.allowsDestination` uses for the
9934
+ * destination floor (measured at 1.93 ns/call when off).
9935
+ *
9936
+ * ## Why a channel emits at `info`
9937
+ *
9938
+ * `loki-logging.addon.ts` pins the destination default at `info` and
9939
+ * `loki-destination.ts` drops everything below it, so a line emitted at
9940
+ * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
9941
+ * minutes. A diagnostic that cannot be read an hour later is worse than no
9942
+ * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
9943
+ * emits at the channel's declared level, whose schema floor is `info`.
9944
+ */
9945
+ /**
9946
+ * The level a channel writes at once armed.
9947
+ *
9948
+ * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
9949
+ * not leave the process for Loki, and the whole point of arming a channel is
9950
+ * to read it later.
9951
+ */
9952
+ var LogChannelLevelSchema = _enum([
9953
+ "info",
9954
+ "warn",
9955
+ "error"
9956
+ ]);
9957
+ /**
9958
+ * What an addon declares about one channel. No value, no state — a
9959
+ * declaration is inert.
9960
+ */
9961
+ var LogChannelDescriptorSchema = object({
9962
+ /**
9963
+ * Dotted `area.thing`, unique across the workspace. `area` is conventionally
9964
+ * the addon's short name so an operator reading a channel list can tell who
9965
+ * owns it without a second lookup.
9966
+ */
9967
+ name: string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
9968
+ /** One sentence: what the operator will SEE after arming it. */
9969
+ description: string().min(1),
9970
+ /** The level its lines are emitted at. Never below `info`. */
9971
+ defaultLevel: LogChannelLevelSchema,
9972
+ /**
9973
+ * Whether this channel can be narrowed to a camera.
9974
+ *
9975
+ * `true` is a PROMISE with two halves, and both must hold: the gate is
9976
+ * consulted with the numeric device id, AND every line the channel admits
9977
+ * carries `tags: { deviceId }` with that same numeric id. The second half is
9978
+ * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
9979
+ * keeps `deviceId` out of the stream labels for cardinality, so the tag in
9980
+ * the body is the only way to filter.
9981
+ *
9982
+ * A channel whose lines carry the device only in `meta` (or not at all) is
9983
+ * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
9984
+ * the operator narrows to one camera, sees nothing, and concludes the code
9985
+ * path was never taken.
9986
+ */
9987
+ perDevice: boolean()
9988
+ });
9989
+ /**
9990
+ * An armed window over one channel, as the document hands it to a mirror.
9991
+ *
9992
+ * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
9993
+ * expires by itself, which is the one failure a boolean cannot avoid.
9994
+ */
9995
+ var LogChannelWindowSchema = object({
9996
+ channel: string().min(1),
9997
+ /** Epoch ms the window closes at. */
9998
+ armedUntilMs: number(),
9999
+ /** `null` = every camera. A non-empty list narrows to those numeric ids. */
10000
+ deviceIds: array(number().int()).readonly().nullable()
10001
+ });
9998
10002
  var MODEL_FORMATS = [
9999
10003
  "onnx",
10000
10004
  "coreml",
@@ -23044,7 +23048,7 @@ method(object({
23044
23048
  downloadId: string(),
23045
23049
  offset: number(),
23046
23050
  length: number()
23047
- }), _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({
23051
+ }), _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({
23048
23052
  createdAt: true,
23049
23053
  updatedAt: true
23050
23054
  }), StorageLocationSchema, {
@@ -39897,12 +39901,6 @@ Object.freeze({
39897
39901
  addonId: null,
39898
39902
  access: "view"
39899
39903
  },
39900
- "storage.getDefaultLocation": {
39901
- capName: "storage",
39902
- capScope: "system",
39903
- addonId: null,
39904
- access: "view"
39905
- },
39906
39904
  "storage.list": {
39907
39905
  capName: "storage",
39908
39906
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -8716,111 +8716,6 @@ var CameraSwitchGroupSchema = object({
8716
8716
  fetchedAt: number()
8717
8717
  });
8718
8718
  /**
8719
- * Per-component log CHANNELS — the gate a hot path consults, and the registry
8720
- * an addon declares its channels in.
8721
- *
8722
- * ## Two axes, deliberately separated
8723
- *
8724
- * - **DECLARATION** — which channels exist. Only the addon knows:
8725
- * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
8726
- * baichuan/handshake. A hand-wired central list rots at the first addition,
8727
- * and rots silently. So a channel is declared where it is consulted, and the
8728
- * `log-channels` capability enumerates the declarations.
8729
- * - **VALUE** — at which level, for which scope, until when. That stays ONE
8730
- * thing: the logging settings document on the `system` cap. Two authorities
8731
- * over the values is the exact defect
8732
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
8733
- * remove; re-introducing it from the cure side would be grotesque.
8734
- *
8735
- * Nothing in this file reads a clock, an env var or a store. The registry is
8736
- * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
8737
- * the hot path with a value somebody actually read, and by
8738
- * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
8739
- * never reaches here, so it can neither disarm an armed channel nor arm a
8740
- * disarmed one (D49).
8741
- *
8742
- * ## The canonical call shape
8743
- *
8744
- * ```ts
8745
- * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
8746
- * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
8747
- * }
8748
- * ```
8749
- *
8750
- * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
8751
- * read. Disarmed, a call site costs one load and one branch, and the `extras`
8752
- * object literal is never constructed because it lives inside the branch. It
8753
- * is the same shape already proven in production at `stream-broker.ts:1650`,
8754
- * and the same discipline `LoggingGate.allowsDestination` uses for the
8755
- * destination floor (measured at 1.93 ns/call when off).
8756
- *
8757
- * ## Why a channel emits at `info`
8758
- *
8759
- * `loki-logging.addon.ts` pins the destination default at `info` and
8760
- * `loki-destination.ts` drops everything below it, so a line emitted at
8761
- * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
8762
- * minutes. A diagnostic that cannot be read an hour later is worse than no
8763
- * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
8764
- * emits at the channel's declared level, whose schema floor is `info`.
8765
- */
8766
- /**
8767
- * The level a channel writes at once armed.
8768
- *
8769
- * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
8770
- * not leave the process for Loki, and the whole point of arming a channel is
8771
- * to read it later.
8772
- */
8773
- var LogChannelLevelSchema = _enum([
8774
- "info",
8775
- "warn",
8776
- "error"
8777
- ]);
8778
- /**
8779
- * What an addon declares about one channel. No value, no state — a
8780
- * declaration is inert.
8781
- */
8782
- var LogChannelDescriptorSchema = object({
8783
- /**
8784
- * Dotted `area.thing`, unique across the workspace. `area` is conventionally
8785
- * the addon's short name so an operator reading a channel list can tell who
8786
- * owns it without a second lookup.
8787
- */
8788
- name: string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
8789
- /** One sentence: what the operator will SEE after arming it. */
8790
- description: string().min(1),
8791
- /** The level its lines are emitted at. Never below `info`. */
8792
- defaultLevel: LogChannelLevelSchema,
8793
- /**
8794
- * Whether this channel can be narrowed to a camera.
8795
- *
8796
- * `true` is a PROMISE with two halves, and both must hold: the gate is
8797
- * consulted with the numeric device id, AND every line the channel admits
8798
- * carries `tags: { deviceId }` with that same numeric id. The second half is
8799
- * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
8800
- * keeps `deviceId` out of the stream labels for cardinality, so the tag in
8801
- * the body is the only way to filter.
8802
- *
8803
- * A channel whose lines carry the device only in `meta` (or not at all) is
8804
- * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
8805
- * the operator narrows to one camera, sees nothing, and concludes the code
8806
- * path was never taken.
8807
- */
8808
- perDevice: boolean()
8809
- });
8810
- /**
8811
- * An armed window over one channel, as the document hands it to a mirror.
8812
- *
8813
- * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
8814
- * expires by itself, which is the one failure a boolean cannot avoid.
8815
- */
8816
- var LogChannelWindowSchema = object({
8817
- channel: string().min(1),
8818
- /** Epoch ms the window closes at. */
8819
- armedUntilMs: number(),
8820
- /** `null` = every camera. A non-empty list narrows to those numeric ids. */
8821
- deviceIds: array(number().int()).readonly().nullable()
8822
- });
8823
- /**
8824
8719
  * Ops-log — the durable, append-only operations audit shared by the
8825
8720
  * recordings and events management surfaces.
8826
8721
  *
@@ -9766,8 +9661,11 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
9766
9661
  * `STORAGE_LOCATION_CARDINALITY` map has been removed.
9767
9662
  *
9768
9663
  * `id` is a stable namespaced string of the form `<type>:<slug>`.
9769
- * The default location for a type uses `id === <type>:default` by
9770
- * convention (the bare type ref like `'backups'` resolves to it).
9664
+ * The seed names its first instance `<type>:default` — a NAME, not a flag.
9665
+ * There is no default location any more (D383): `enabled` is the whole write
9666
+ * model, and a bare type ref resolves to the sole location of the type, or —
9667
+ * transitionally, only while legacy NULL-stamped rows exist — to the row whose
9668
+ * slug is `default`.
9771
9669
  *
9772
9670
  * `isSystem` is a legacy persisted flag. Seed still creates the initial
9773
9671
  * `<type>:default` locations; the flag is no longer a lock, a badge, or a
@@ -9788,21 +9686,20 @@ var StorageLocationSchema = object({
9788
9686
  * flag at upsert time, not here (the schema is provider-agnostic).
9789
9687
  */
9790
9688
  nodeId: string().optional(),
9791
- isDefault: boolean().default(false),
9792
9689
  isSystem: boolean().default(false),
9793
9690
  /**
9794
- * Operator opt-in: whether consumers that BALANCE across several locations
9795
- * of a type may write here. Recordings reads it today; event media and
9796
- * backups are the next consumers, which is why the flag lives on the
9797
- * location rather than in any one addon's store nothing has to be
9798
- * extended to add the next consumer.
9691
+ * THE write switch, and the only one (D383). `enabled: true` means every
9692
+ * consumer that chooses a write target for this type may write here, and all
9693
+ * enabled locations of a type are used TOGETHER; `false` means read-only
9694
+ * still read, still played back, still age-swept, still drained, never
9695
+ * written.
9799
9696
  *
9800
- * OPTIONAL, and ABSENT MEANS ACTIVE. Every location persisted before the
9801
- * flag existed reads back with no flag and keeps working exactly as before;
9802
- * that is the whole compat story, and it is why no migration ships with it.
9803
- * A newly CREATED sibling is stamped `false` by the orchestrator (creating a
9804
- * disk must not silently start writing to it); the default of a type is
9805
- * always stamped `true`.
9697
+ * OPTIONAL only for the wire: an upsert that omits it means "leave what is
9698
+ * stored" on an update and "born inert unless it is the first location of its
9699
+ * type" on a create. On a PERSISTED row absence is legacy and it means
9700
+ * enabled {@link isLocationEnabled} is the one place that says so, and the
9701
+ * orchestrator stamps every flagless row `true` once at hydrate so absence
9702
+ * stops existing rather than being re-derived on every read.
9806
9703
  */
9807
9704
  enabled: boolean().optional(),
9808
9705
  /** COMPUTED at read time by the orchestrator (statfs of the backing volume
@@ -9815,10 +9712,12 @@ var StorageLocationSchema = object({
9815
9712
  createdAt: number(),
9816
9713
  updatedAt: number()
9817
9714
  });
9715
+ object({ isDefault: boolean().optional() });
9818
9716
  /**
9819
9717
  * Reference accepted by consumer-facing `api.storage.*` calls.
9820
9718
  * Either:
9821
- * - a `StorageLocationType` (e.g. `'backups'`) → orchestrator resolves to the default of that type
9719
+ * - a `StorageLocationType` (e.g. `'backups'`) → the sole location of that type
9720
+ * (transitionally, the `<type>:default`-slugged row when several exist)
9822
9721
  * - a fully-qualified id (e.g. `'backups:nas-01'`) → addresses a specific instance
9823
9722
  *
9824
9723
  * The orchestrator's `resolveRef(ref)` handles both cases.
@@ -9994,6 +9893,111 @@ var DecoderSessionConfigSchema = object({
9994
9893
  */
9995
9894
  debug: boolean().optional()
9996
9895
  });
9896
+ /**
9897
+ * Per-component log CHANNELS — the gate a hot path consults, and the registry
9898
+ * an addon declares its channels in.
9899
+ *
9900
+ * ## Two axes, deliberately separated
9901
+ *
9902
+ * - **DECLARATION** — which channels exist. Only the addon knows:
9903
+ * `stream-broker` knows webrtc/ICE/RTP, `provider-reolink` knows
9904
+ * baichuan/handshake. A hand-wired central list rots at the first addition,
9905
+ * and rots silently. So a channel is declared where it is consulted, and the
9906
+ * `log-channels` capability enumerates the declarations.
9907
+ * - **VALUE** — at which level, for which scope, until when. That stays ONE
9908
+ * thing: the logging settings document on the `system` cap. Two authorities
9909
+ * over the values is the exact defect
9910
+ * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
9911
+ * remove; re-introducing it from the cure side would be grotesque.
9912
+ *
9913
+ * Nothing in this file reads a clock, an env var or a store. The registry is
9914
+ * a MIRROR: it is moved only by {@link LogChannelRegistry.apply}, called off
9915
+ * the hot path with a value somebody actually read, and by
9916
+ * {@link LogChannelRegistry.tick}, called on a timer. A store read that fails
9917
+ * never reaches here, so it can neither disarm an armed channel nor arm a
9918
+ * disarmed one (D49).
9919
+ *
9920
+ * ## The canonical call shape
9921
+ *
9922
+ * ```ts
9923
+ * if (CH_RTP.on && CH_RTP.wants(deviceId)) {
9924
+ * CH_RTP.log(logger, 'rtp subscriber added', { tags: { deviceId }, meta: { ssrc } })
9925
+ * }
9926
+ * ```
9927
+ *
9928
+ * `on` is a plain boolean FIELD — never a getter — and it is the FIRST thing
9929
+ * read. Disarmed, a call site costs one load and one branch, and the `extras`
9930
+ * object literal is never constructed because it lives inside the branch. It
9931
+ * is the same shape already proven in production at `stream-broker.ts:1650`,
9932
+ * and the same discipline `LoggingGate.allowsDestination` uses for the
9933
+ * destination floor (measured at 1.93 ns/call when off).
9934
+ *
9935
+ * ## Why a channel emits at `info`
9936
+ *
9937
+ * `loki-logging.addon.ts` pins the destination default at `info` and
9938
+ * `loki-destination.ts` drops everything below it, so a line emitted at
9939
+ * `debug` never reaches Loki and the hub's in-memory ring only holds ~35
9940
+ * minutes. A diagnostic that cannot be read an hour later is worse than no
9941
+ * diagnostic, because it looks done. {@link LogChannelGate.log} therefore
9942
+ * emits at the channel's declared level, whose schema floor is `info`.
9943
+ */
9944
+ /**
9945
+ * The level a channel writes at once armed.
9946
+ *
9947
+ * `debug` is absent ON PURPOSE and not by omission: below `info` the line does
9948
+ * not leave the process for Loki, and the whole point of arming a channel is
9949
+ * to read it later.
9950
+ */
9951
+ var LogChannelLevelSchema = _enum([
9952
+ "info",
9953
+ "warn",
9954
+ "error"
9955
+ ]);
9956
+ /**
9957
+ * What an addon declares about one channel. No value, no state — a
9958
+ * declaration is inert.
9959
+ */
9960
+ var LogChannelDescriptorSchema = object({
9961
+ /**
9962
+ * Dotted `area.thing`, unique across the workspace. `area` is conventionally
9963
+ * the addon's short name so an operator reading a channel list can tell who
9964
+ * owns it without a second lookup.
9965
+ */
9966
+ name: string().min(3).regex(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/, "a channel name is dotted lower-kebab, e.g. area.thing"),
9967
+ /** One sentence: what the operator will SEE after arming it. */
9968
+ description: string().min(1),
9969
+ /** The level its lines are emitted at. Never below `info`. */
9970
+ defaultLevel: LogChannelLevelSchema,
9971
+ /**
9972
+ * Whether this channel can be narrowed to a camera.
9973
+ *
9974
+ * `true` is a PROMISE with two halves, and both must hold: the gate is
9975
+ * consulted with the numeric device id, AND every line the channel admits
9976
+ * carries `tags: { deviceId }` with that same numeric id. The second half is
9977
+ * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
9978
+ * keeps `deviceId` out of the stream labels for cardinality, so the tag in
9979
+ * the body is the only way to filter.
9980
+ *
9981
+ * A channel whose lines carry the device only in `meta` (or not at all) is
9982
+ * declared `false`. Declaring it `true` anyway would be a lie the UI repeats:
9983
+ * the operator narrows to one camera, sees nothing, and concludes the code
9984
+ * path was never taken.
9985
+ */
9986
+ perDevice: boolean()
9987
+ });
9988
+ /**
9989
+ * An armed window over one channel, as the document hands it to a mirror.
9990
+ *
9991
+ * A window is a DEADLINE, never a flag (ADR-0244): a channel somebody forgot
9992
+ * expires by itself, which is the one failure a boolean cannot avoid.
9993
+ */
9994
+ var LogChannelWindowSchema = object({
9995
+ channel: string().min(1),
9996
+ /** Epoch ms the window closes at. */
9997
+ armedUntilMs: number(),
9998
+ /** `null` = every camera. A non-empty list narrows to those numeric ids. */
9999
+ deviceIds: array(number().int()).readonly().nullable()
10000
+ });
9997
10001
  var MODEL_FORMATS = [
9998
10002
  "onnx",
9999
10003
  "coreml",
@@ -23043,7 +23047,7 @@ method(object({
23043
23047
  downloadId: string(),
23044
23048
  offset: number(),
23045
23049
  length: number()
23046
- }), _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({
23050
+ }), _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({
23047
23051
  createdAt: true,
23048
23052
  updatedAt: true
23049
23053
  }), StorageLocationSchema, {
@@ -39896,12 +39900,6 @@ Object.freeze({
39896
39900
  addonId: null,
39897
39901
  access: "view"
39898
39902
  },
39899
- "storage.getDefaultLocation": {
39900
- capName: "storage",
39901
- capScope: "system",
39902
- addonId: null,
39903
- access: "view"
39904
- },
39905
39903
  "storage.list": {
39906
39904
  capName: "storage",
39907
39905
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-petkit",
3
- "version": "0.2.78",
3
+ "version": "0.2.79",
4
4
  "description": "PetKit smart-feeder device-provider addon for CamStack — wraps the @apocaliss92/nodepetkit PetKit cloud client",
5
5
  "keywords": [
6
6
  "camstack",