@camstack/system 1.2.69 → 1.2.71

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 (70) hide show
  1. package/dist/addon-runner.js +6 -6
  2. package/dist/addon-runner.mjs +3 -3
  3. package/dist/addon-utils.js +11 -11
  4. package/dist/addon-utils.mjs +1 -1
  5. package/dist/auth/auth-manager.d.ts +13 -29
  6. package/dist/auth/scope-matcher.d.ts +6 -5
  7. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +3 -3
  8. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +2 -2
  9. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +3 -3
  10. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +2 -2
  11. package/dist/builtins/alerts/alerts.addon.js +1 -1
  12. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  13. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +8 -8
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +6 -6
  15. package/dist/builtins/console-logging/index.js +1 -1
  16. package/dist/builtins/console-logging/index.mjs +1 -1
  17. package/dist/builtins/core-blocks/core-blocks.addon.js +3 -3
  18. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  19. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  20. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  21. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  22. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  23. package/dist/builtins/hub-forwarder/index.js +1 -1
  24. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  25. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  26. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  27. package/dist/builtins/local-auth/index.d.ts +0 -1
  28. package/dist/builtins/local-auth/index.js +0 -1
  29. package/dist/builtins/local-auth/index.mjs +2 -2
  30. package/dist/builtins/local-auth/local-auth.addon.js +4878 -4883
  31. package/dist/builtins/local-auth/local-auth.addon.mjs +4879 -4883
  32. package/dist/builtins/local-auth/oauth-grants.d.ts +15 -0
  33. package/dist/builtins/local-network/local-network.addon.js +1 -1
  34. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  35. package/dist/builtins/loki-logging/index.js +1 -1
  36. package/dist/builtins/loki-logging/index.mjs +1 -1
  37. package/dist/builtins/native-metrics/native-metrics.addon.js +5 -5
  38. package/dist/builtins/native-metrics/native-metrics.addon.mjs +4 -4
  39. package/dist/builtins/platform-probe/index.js +4 -4
  40. package/dist/builtins/platform-probe/index.mjs +3 -3
  41. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  42. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  43. package/dist/builtins/snapshot/index.js +2 -2
  44. package/dist/builtins/snapshot/index.mjs +2 -2
  45. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +4 -4
  46. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +3 -3
  47. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  48. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  49. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +3 -3
  50. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +2 -2
  51. package/dist/builtins/system-config/system-config.addon.js +1 -1
  52. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  53. package/dist/builtins/winston-logging/index.js +1 -1
  54. package/dist/builtins/winston-logging/index.mjs +1 -1
  55. package/dist/{dist-C-QzFJ8v.mjs → dist-Daxx9CB0.mjs} +139 -5
  56. package/dist/{dist-D7wC-S4p.js → dist-I0WgqQQ-.js} +150 -10
  57. package/dist/{model-download-service-CTBHzORJ.mjs → file-data-plane-CuE_hBli.mjs} +848 -848
  58. package/dist/index.d.ts +73 -81
  59. package/dist/index.js +1302 -1278
  60. package/dist/index.mjs +1283 -1259
  61. package/dist/kernel/capability-registry.d.ts +26 -0
  62. package/dist/kernel/config-schema.d.ts +1 -1
  63. package/dist/kernel/transport/parent-unowned-call.d.ts +27 -0
  64. package/dist/{manifest-python-deps-Dz1ryHIN.mjs → manifest-python-deps-BdWxKNvu.mjs} +49 -47
  65. package/dist/{manifest-python-deps-BE6l8Y4W.js → manifest-python-deps-BqIpg0C7.js} +49 -47
  66. package/package.json +1 -4
  67. package/dist/builtins/local-auth/homeassistant-integration.d.ts +0 -7
  68. package/dist/{model-download-service-Caj1kaSi.js → file-data-plane-DUHPHa-Y.js} +847 -847
  69. package/dist/{resource-monitor-BkP504Vq.mjs → resource-monitor-BWmQ5i-o.mjs} +1 -1
  70. package/dist/{resource-monitor-DNNomR-i.js → resource-monitor-CdnzxBLP.js} +1 -1
@@ -1,5 +1,13 @@
1
1
  import { ISsoBridgeProvider, TokenScope } from '@camstack/types';
2
2
  import { OauthSessionManager } from './oauth-session-manager.js';
3
+ /**
4
+ * The refresh lifetime for an integration whose descriptor declares none.
5
+ * 30 days — the value every link used before `refreshTokenTtlSec` existed, kept
6
+ * as the default so an integration that says nothing is unchanged.
7
+ */
8
+ export declare const DEFAULT_REFRESH_TTL_SEC = 2592000;
9
+ /** Seconds, or `'never'` for a refresh token minted with no `exp` claim. */
10
+ export type RefreshTtl = number | 'never';
3
11
  interface IssueCodeInput {
4
12
  integrationId: string;
5
13
  userId: string;
@@ -8,6 +16,13 @@ interface IssueCodeInput {
8
16
  redirectUri: string;
9
17
  hubUrl: string;
10
18
  codeChallenge?: string;
19
+ /**
20
+ * From the integration's `OauthIntegrationDescriptor.refreshTokenTtlSec`.
21
+ * Baked into the CODE so it travels with the link: re-reading the descriptor
22
+ * at refresh time would let an edit retroactively change the lifetime of a
23
+ * grant the operator already consented to.
24
+ */
25
+ refreshTtlSec?: RefreshTtl;
11
26
  }
12
27
  /**
13
28
  * PKCE S256 check (RFC 7636 §4.6): `BASE64URL(SHA256(verifier)) === challenge`.
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-D7wC-S4p.js");
3
+ const require_dist = require("../../dist-I0WgqQQ-.js");
4
4
  let node_os = require("node:os");
5
5
  node_os = require_chunk.__toESM(node_os);
6
6
  //#region src/builtins/local-network/local-network.addon.ts
@@ -1,4 +1,4 @@
1
- import { K as localNetworkCapability, pt as BaseAddon, zt as EventCategory } from "../../dist-C-QzFJ8v.mjs";
1
+ import { Bt as EventCategory, K as localNetworkCapability, mt as BaseAddon } from "../../dist-Daxx9CB0.mjs";
2
2
  import * as os from "node:os";
3
3
  //#region src/builtins/local-network/local-network.addon.ts
4
4
  /**
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
7
7
  //#region src/builtins/loki-logging/loki-payload.ts
8
8
  /**
9
9
  * Loki rejects a label name that is not a valid Prometheus label
@@ -1,4 +1,4 @@
1
- import { pt as BaseAddon, q as logDestinationCapability } from "../../dist-C-QzFJ8v.mjs";
1
+ import { mt as BaseAddon, q as logDestinationCapability } from "../../dist-Daxx9CB0.mjs";
2
2
  //#region src/builtins/loki-logging/loki-payload.ts
3
3
  /**
4
4
  * Loki rejects a label name that is not a valid Prometheus label
@@ -3,13 +3,13 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
7
- let node_fs = require("node:fs");
8
- node_fs = require_chunk.__toESM(node_fs);
9
- let node_util = require("node:util");
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
10
7
  let node_child_process = require("node:child_process");
8
+ let node_util = require("node:util");
11
9
  let node_os = require("node:os");
12
10
  node_os = require_chunk.__toESM(node_os);
11
+ let node_fs = require("node:fs");
12
+ node_fs = require_chunk.__toESM(node_fs);
13
13
  //#region src/builtins/native-metrics/native-metrics-provider.ts
14
14
  var IS_DARWIN = node_os.platform() === "darwin";
15
15
  var IS_LINUX = node_os.platform() === "linux";
@@ -123,7 +123,7 @@ var NativeMetricsProvider = class {
123
123
  return getCpuTemperatureInternal();
124
124
  }
125
125
  async getProcessStats(input) {
126
- const { getPidStats } = await Promise.resolve().then(() => require("../../resource-monitor-DNNomR-i.js")).then((n) => n.resource_monitor_exports);
126
+ const { getPidStats } = await Promise.resolve().then(() => require("../../resource-monitor-CdnzxBLP.js")).then((n) => n.resource_monitor_exports);
127
127
  const raw = await getPidStats(input.pids);
128
128
  const result = [];
129
129
  for (const [pid, s] of raw) result.push({
@@ -1,8 +1,8 @@
1
- import { Et as createEvent, X as metricsProviderCapability, pt as BaseAddon, zt as EventCategory } from "../../dist-C-QzFJ8v.mjs";
2
- import * as fs from "node:fs";
3
- import { promisify } from "node:util";
1
+ import { Bt as EventCategory, Dt as createEvent, X as metricsProviderCapability, mt as BaseAddon } from "../../dist-Daxx9CB0.mjs";
4
2
  import { execFile, execFileSync } from "node:child_process";
3
+ import { promisify } from "node:util";
5
4
  import * as os from "node:os";
5
+ import * as fs from "node:fs";
6
6
  //#region src/builtins/native-metrics/native-metrics-provider.ts
7
7
  var IS_DARWIN = os.platform() === "darwin";
8
8
  var IS_LINUX = os.platform() === "linux";
@@ -116,7 +116,7 @@ var NativeMetricsProvider = class {
116
116
  return getCpuTemperatureInternal();
117
117
  }
118
118
  async getProcessStats(input) {
119
- const { getPidStats } = await import("../../resource-monitor-BkP504Vq.mjs").then((n) => n.r);
119
+ const { getPidStats } = await import("../../resource-monitor-BWmQ5i-o.mjs").then((n) => n.r);
120
120
  const raw = await getPidStats(input.pids);
121
121
  const result = [];
122
122
  for (const [pid, s] of raw) result.push({
@@ -3,13 +3,13 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
7
- let node_fs = require("node:fs");
8
- node_fs = require_chunk.__toESM(node_fs);
9
- let node_util = require("node:util");
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
10
7
  let node_child_process = require("node:child_process");
8
+ let node_util = require("node:util");
11
9
  let node_os = require("node:os");
12
10
  node_os = require_chunk.__toESM(node_os);
11
+ let node_fs = require("node:fs");
12
+ node_fs = require_chunk.__toESM(node_fs);
13
13
  //#region src/builtins/platform-probe/coral-accelerators.ts
14
14
  /**
15
15
  * Coral USB Edge TPU USB identifiers.
@@ -1,9 +1,9 @@
1
1
  import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
2
- import { Ot as emitReadiness, P as enumerateInferenceDevices, ft as errMsg, pt as BaseAddon, rt as scoreRuntimes, tt as platformProbeCapability, zt as EventCategory } from "../../dist-C-QzFJ8v.mjs";
3
- import * as fs from "node:fs";
4
- import { promisify } from "node:util";
2
+ import { Bt as EventCategory, P as enumerateInferenceDevices, et as platformProbeCapability, it as scoreRuntimes, kt as emitReadiness, mt as BaseAddon, pt as errMsg } from "../../dist-Daxx9CB0.mjs";
5
3
  import { execFile } from "node:child_process";
4
+ import { promisify } from "node:util";
6
5
  import * as os from "node:os";
6
+ import * as fs from "node:fs";
7
7
  //#region src/builtins/platform-probe/coral-accelerators.ts
8
8
  /**
9
9
  * Coral USB Edge TPU USB identifiers.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
7
7
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
8
8
  /**
9
9
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -1,4 +1,4 @@
1
- import { pt as BaseAddon, zt as EventCategory } from "../../dist-C-QzFJ8v.mjs";
1
+ import { Bt as EventCategory, mt as BaseAddon } from "../../dist-Daxx9CB0.mjs";
2
2
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
3
3
  /**
4
4
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -3,10 +3,10 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
7
- let _camstack_types_node = require("@camstack/types/node");
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
8
7
  let zod = require("zod");
9
8
  let node_crypto = require("node:crypto");
9
+ let _camstack_types_node = require("@camstack/types/node");
10
10
  let node_child_process = require("node:child_process");
11
11
  //#region src/builtins/snapshot/snapshot-coalescing.ts
12
12
  /**
@@ -1,7 +1,7 @@
1
- import { C as bareAddonId, Mt as nodePin, _t as DeviceFeature, at as snapshotCapability, ct as streamQualityLabel, ft as errMsg, i as BatteryStatusSchema, pt as BaseAddon, yt as DeviceType } from "../../dist-C-QzFJ8v.mjs";
2
- import { signExpiringUrl, verifyExpiringUrl } from "@camstack/types/node";
1
+ import { C as bareAddonId, Nt as nodePin, bt as DeviceType, i as BatteryStatusSchema, lt as streamQualityLabel, mt as BaseAddon, ot as snapshotCapability, pt as errMsg, vt as DeviceFeature } from "../../dist-Daxx9CB0.mjs";
3
2
  import { z } from "zod";
4
3
  import { randomUUID } from "node:crypto";
4
+ import { signExpiringUrl, verifyExpiringUrl } from "@camstack/types/node";
5
5
  import { execFile, spawn } from "node:child_process";
6
6
  //#region src/builtins/snapshot/snapshot-coalescing.ts
7
7
  /**
@@ -3,14 +3,14 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
7
7
  let node_crypto = require("node:crypto");
8
- let node_fs = require("node:fs");
9
- node_fs = require_chunk.__toESM(node_fs);
8
+ let node_fs_promises = require("node:fs/promises");
10
9
  let node_path = require("node:path");
11
10
  node_path = require_chunk.__toESM(node_path);
12
11
  let node_os = require("node:os");
13
- let node_fs_promises = require("node:fs/promises");
12
+ let node_fs = require("node:fs");
13
+ node_fs = require_chunk.__toESM(node_fs);
14
14
  //#region src/builtins/sqlite-storage/path-guard.ts
15
15
  /**
16
16
  * Allowed-root containment guard for the filesystem-browse cap. Pure +
@@ -1,10 +1,10 @@
1
- import { R as filesystemBrowseCapability, pt as BaseAddon, st as storageProviderCapability } from "../../dist-C-QzFJ8v.mjs";
1
+ import { R as filesystemBrowseCapability, ct as storageProviderCapability, mt as BaseAddon } from "../../dist-Daxx9CB0.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
- import * as fs from "node:fs";
3
+ import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
5
5
  import { basename, dirname, join, resolve, sep } from "node:path";
6
6
  import { homedir } from "node:os";
7
- import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
7
+ import * as fs from "node:fs";
8
8
  //#region src/builtins/sqlite-storage/path-guard.ts
9
9
  /**
10
10
  * Allowed-root containment guard for the filesystem-browse cap. Pure +
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let node_fs = require("node:fs");
9
9
  let node_module = require("node:module");
@@ -1,4 +1,4 @@
1
- import { C as bareAddonId, Ct as asJsonObject, O as dataStoreProviderCapability, Pt as parseJsonUnknown, dt as vectorStoreCapability, f as RUNTIME_DEFAULTS, ft as errMsg, k as decodeVectorBase64, pt as BaseAddon, ut as vectorDimFromBase64 } from "../../dist-C-QzFJ8v.mjs";
1
+ import { C as bareAddonId, Ft as parseJsonUnknown, O as dataStoreProviderCapability, dt as vectorDimFromBase64, f as RUNTIME_DEFAULTS, ft as vectorStoreCapability, k as decodeVectorBase64, mt as BaseAddon, pt as errMsg, wt as asJsonObject } from "../../dist-Daxx9CB0.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { statSync } from "node:fs";
@@ -3,11 +3,11 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
7
- let node_path = require("node:path");
8
- node_path = require_chunk.__toESM(node_path);
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
9
7
  let node_fs_promises = require("node:fs/promises");
10
8
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
9
+ let node_path = require("node:path");
10
+ node_path = require_chunk.__toESM(node_path);
11
11
  let _camstack_system = require("@camstack/system");
12
12
  //#region src/builtins/storage-orchestrator/storage-orchestrator.service.ts
13
13
  var SESSION_VOCABULARY = {
@@ -1,6 +1,6 @@
1
- import { Nt as parseJsonObject, h as StorageLocationTypeSchema, it as settingsStoreCapability, ot as storageCapability, pt as BaseAddon } from "../../dist-C-QzFJ8v.mjs";
2
- import * as path$1 from "node:path";
1
+ import { Pt as parseJsonObject, at as settingsStoreCapability, h as StorageLocationTypeSchema, mt as BaseAddon, st as storageCapability } from "../../dist-Daxx9CB0.mjs";
3
2
  import * as fs from "node:fs/promises";
3
+ import * as path$1 from "node:path";
4
4
  import { buildStorageLocationRegistry } from "@camstack/system";
5
5
  //#region src/builtins/storage-orchestrator/storage-orchestrator.service.ts
6
6
  var SESSION_VOCABULARY = {
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
7
7
  //#region src/builtins/system-config/system-config.addon.ts
8
8
  /**
9
9
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -1,4 +1,4 @@
1
- import { At as hydrateSchema, ft as errMsg, pt as BaseAddon } from "../../dist-C-QzFJ8v.mjs";
1
+ import { jt as hydrateSchema, mt as BaseAddon, pt as errMsg } from "../../dist-Daxx9CB0.mjs";
2
2
  //#region src/builtins/system-config/system-config.addon.ts
3
3
  /**
4
4
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D7wC-S4p.js");
6
+ const require_dist = require("../../dist-I0WgqQQ-.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  let node_path = require("node:path");
9
9
  node_path = require_chunk.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { pt as BaseAddon, q as logDestinationCapability } from "../../dist-C-QzFJ8v.mjs";
1
+ import { mt as BaseAddon, q as logDestinationCapability } from "../../dist-Daxx9CB0.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  import * as path$1 from "node:path";
4
4
  import path from "node:path";
@@ -4148,6 +4148,24 @@ var ConvertResultSchema = z.object({
4148
4148
  artifacts: z.array(ConvertArtifactSchema).readonly()
4149
4149
  });
4150
4150
  /**
4151
+ * True if the scope set grants `access` on device-scoped capabilities.
4152
+ * A `category:device` grant covers every device cap (the broad grant).
4153
+ */
4154
+ function scopesAllowDeviceCap(scopes, access) {
4155
+ return scopes.some((s) => s.type === "category" && s.target === "device" && s.access.includes(access));
4156
+ }
4157
+ /**
4158
+ * True if the scope set names this addon with at least `access`.
4159
+ *
4160
+ * Deliberately NOT satisfied by `category:device`: a grant over per-camera
4161
+ * capabilities says nothing about an addon's own HTTP surface, and conflating
4162
+ * the two is precisely the confusion that let an Alexa token drive Home
4163
+ * Assistant's command route.
4164
+ */
4165
+ function scopesAllowAddon(scopes, addonId, access) {
4166
+ return scopes.some((s) => s.type === "addon" && s.target === addonId && s.access.includes(access));
4167
+ }
4168
+ /**
4151
4169
  * Error types for the safe expression engine. Two distinct classes so callers
4152
4170
  * can tell a compile-time (grammar) failure from a runtime (evaluation)
4153
4171
  * failure — both are non-fatal to the host: read paths degrade to "skip link".
@@ -13022,6 +13040,76 @@ var ScopedTokenSchema = z.object({
13022
13040
  * Each provider returns a static descriptor; the core enumerates them
13023
13041
  * to validate the `integration=` query param and resolve the consent
13024
13042
  * label + the scopes baked into the issued token.
13043
+ *
13044
+ * ## Declaring one
13045
+ *
13046
+ * An OAuth client is integration-specific knowledge — who the client is, what
13047
+ * it may ask for, where it may be sent — so it is declared by the ADDON that
13048
+ * owns the integration, never by the kernel and never as a branch inside
13049
+ * `oauth2-routes.ts` ([D101](../../../../docs/decisions/adr-0101.md)). Three
13050
+ * steps, no others:
13051
+ *
13052
+ * 1. Add `{ "name": "oauth-integration" }` to the addon's `camstack.addons[]`
13053
+ * manifest entry. This is also what tells the hub, at addon-LOAD time, that
13054
+ * a descriptor is owed — see "the boot window" below.
13055
+ * 2. Return a provider from `onInitialize()`:
13056
+ *
13057
+ * ```ts
13058
+ * const provider: IOauthIntegrationProvider = {
13059
+ * getDescriptor: async () => ({
13060
+ * integrationId: 'my-thing', // the `integration=` query param
13061
+ * displayName: 'My Thing',
13062
+ * requestedScopes: [ … ], // see below
13063
+ * allowedRedirectPrefixes: ['https://callback.example/'],
13064
+ * }),
13065
+ * }
13066
+ * return [{ capability: oauthIntegrationCapability, provider }]
13067
+ * ```
13068
+ *
13069
+ * The descriptor must be **static** — it is read on the authorize path, so
13070
+ * never put an await on network or disk behind it, and never register it
13071
+ * behind one either (a provider is registered only once `onInitialize`
13072
+ * RETURNS, so anything awaited before the return delays linking).
13073
+ * 3. Nothing else. There is no allow-list to join, no id to register with the
13074
+ * core, and no per-integration branch anywhere: `/api/oauth2/authorize` and
13075
+ * `/api/oauth2/integrations` are built from this collection alone.
13076
+ *
13077
+ * **Scopes. `requestedScopes` has exactly ONE meaning: what the integration
13078
+ * NEEDS to function.** Not a blast radius, not a conservative
13079
+ * under-declaration, not a description of some other path the addon happens to
13080
+ * have. Derive it from what the client actually calls **with this token** —
13081
+ * every tRPC path against `METHOD_ACCESS_MAP`, plus an `addon:` grant for every
13082
+ * addon HTTP route it posts to — and write the call that justifies each entry
13083
+ * next to it. Two integrations once used this field to mean two different
13084
+ * things; the operator ruled there is one meaning, and any third integration
13085
+ * inherits it (2026-08-09).
13086
+ *
13087
+ * This is not documentation, it is the ENFORCEMENT INPUT. Since
13088
+ * [D103](../../../../docs/decisions/adr-0103.md) the `/addon/:addonId/*` gate
13089
+ * checks an integration token's grant before letting it reach an
13090
+ * `access: 'authenticated'` route, so an **under-declaration is an integration
13091
+ * that stops working** — a missing `addon:` entry means `403 Token scope
13092
+ * mismatch` on every control the client tries to actuate. Widen the descriptor
13093
+ * honestly rather than weakening a check to make a route pass.
13094
+ *
13095
+ * Prefer a narrow `capability:` scope to a `category:` one unless the client
13096
+ * genuinely needs a whole family; a category scope grants every future member
13097
+ * of that category too. `category:system [create]` has been rejected once and
13098
+ * should stay rejected: it hands `addons.installPackage` to an integration.
13099
+ *
13100
+ * Calls the ADDON itself makes over `ctx.api` run as the addon and are not
13101
+ * scope-checked, so they are not what this field describes — but reaching the
13102
+ * addon's route in the first place IS, and that is the entry to declare.
13103
+ *
13104
+ * **The boot window.** An addon registers its provider after its runner forks
13105
+ * and initialises, so between hub start and that moment this collection is
13106
+ * incomplete and an `integrationId` can be legitimately absent. The core does
13107
+ * not wait, poll or cache around this ([D3](../../../../docs/decisions/adr-0003.md)):
13108
+ * it compares the manifest declarers against the registered providers and
13109
+ * answers `503 temporarily_unavailable` (with `Retry-After` and the pending
13110
+ * addon ids) instead of `400 unknown integration`, and reports
13111
+ * `complete: false` on `GET /api/oauth2/integrations`. A client should retry
13112
+ * while the list is incomplete rather than conclude the hub cannot do OAuth.
13025
13113
  */
13026
13114
  var OauthIntegrationDescriptorSchema = z.object({
13027
13115
  /** Stable id used as the `integration=` query param, e.g. 'export-alexa'. */
@@ -13052,7 +13140,30 @@ var OauthIntegrationDescriptorSchema = z.object({
13052
13140
  * present, /api/oauth2/authorize bakes THIS into the code instead of the
13053
13141
  * hub-global `publicHubUrl()`, so a forked exporter addon (which can't set
13054
13142
  * the hub's env) drives the claim that its cloud Lambda routes back on. */
13055
- hubUrl: z.string().optional()
13143
+ hubUrl: z.string().optional(),
13144
+ /**
13145
+ * How long a REFRESH token issued for this integration lives — seconds, or
13146
+ * `'never'` for a token minted with no `exp` claim at all. Omit to keep the
13147
+ * 30-day default, which is what every link used before this field existed.
13148
+ *
13149
+ * Declared here for the same reason `requestedScopes` is: the integration
13150
+ * knows what it needs. Amazon's account linking and a Home Assistant config
13151
+ * entry are both meant to survive indefinitely, and re-linking is a manual
13152
+ * user action, so a 30-day expiry silently unlinks a working integration.
13153
+ *
13154
+ * **The security posture, stated so it is owned deliberately.** A refresh
13155
+ * token that never expires is permanent access if it leaks. What bounds it is
13156
+ * revocation, not time: `oauthRefresh` re-reads the session on every use and
13157
+ * returns `null` once `revokedAt` is set, as does `oauthVerifyAccessToken`.
13158
+ * The one gap is the ACCESS token — it is a plain signed JWT that nothing
13159
+ * re-checks against the session on the `/trpc` and `/addon/*` paths, so
13160
+ * revoking a link takes effect there only after its remaining hour. That hour
13161
+ * is why the access TTL is not configurable.
13162
+ *
13163
+ * The value is baked into the authorization code at `/authorize` and travels
13164
+ * on the tokens, so editing this field changes FUTURE links only.
13165
+ */
13166
+ refreshTokenTtlSec: z.union([z.number().int().positive(), z.literal("never")]).optional()
13056
13167
  });
13057
13168
  var oauthIntegrationCapability = {
13058
13169
  name: "oauth-integration",
@@ -17357,7 +17468,16 @@ var SsoBridgeClaimsSchema = z.object({
17357
17468
  codeChallenge: z.string().optional(),
17358
17469
  /** OAuth session registry id — set on `oauth-access`/`oauth-refresh`
17359
17470
  * tokens so the verify path can check the session is not revoked. */
17360
- sessionId: z.string().optional()
17471
+ sessionId: z.string().optional(),
17472
+ /**
17473
+ * The refresh lifetime this LINK was created with, in seconds, or `'never'`.
17474
+ * Baked into the code at `/authorize` from the integration's descriptor and
17475
+ * carried forward so `oauthRefresh` re-mints with the same lifetime. It rides
17476
+ * on the token rather than being re-read from the descriptor on purpose:
17477
+ * editing a descriptor must not retroactively extend or shorten a link the
17478
+ * operator already consented to.
17479
+ */
17480
+ refreshTtl: z.union([z.number().int().positive(), z.literal("never")]).optional()
17361
17481
  });
17362
17482
  var ssoBridgeCapability = {
17363
17483
  name: "sso-bridge",
@@ -17367,7 +17487,16 @@ var ssoBridgeCapability = {
17367
17487
  methods: {
17368
17488
  signBridgeToken: method(z.object({
17369
17489
  claims: SsoBridgeClaimsSchema,
17370
- ttlSec: z.number().int().positive().optional()
17490
+ /**
17491
+ * Seconds, or `'never'` for a token minted with NO `exp` claim.
17492
+ *
17493
+ * `'never'` is a literal rather than `undefined`/`0` because omitting
17494
+ * this field already means "the 5-minute SSO hand-off default", and
17495
+ * `jwt.sign` THROWS on `{ expiresIn: undefined }` — a "no expiry" that
17496
+ * went through the numeric path would fail at mint time and break
17497
+ * linking rather than produce an eternal token.
17498
+ */
17499
+ ttlSec: z.union([z.number().int().positive(), z.literal("never")]).optional()
17371
17500
  }), z.object({ token: z.string() })),
17372
17501
  verifyBridgeToken: method(z.object({ token: z.string() }), SsoBridgeClaimsSchema.nullable())
17373
17502
  }
@@ -26163,7 +26292,12 @@ var userManagementCapability = {
26163
26292
  hubUrl: z.string(),
26164
26293
  /** PKCE (RFC 7636) S256 challenge. Baked into the signed code; a code
26165
26294
  * that carries one can ONLY be exchanged with the matching verifier. */
26166
- codeChallenge: z.string().optional()
26295
+ codeChallenge: z.string().optional(),
26296
+ /** The integration's declared refresh lifetime — seconds, or `'never'`.
26297
+ * From `OauthIntegrationDescriptor.refreshTokenTtlSec`. Baked into the
26298
+ * code so the link carries its own lifetime; omit for the 30-day
26299
+ * default. */
26300
+ refreshTtlSec: z.union([z.number().int().positive(), z.literal("never")]).optional()
26167
26301
  }), z.object({ code: z.string() }), {
26168
26302
  kind: "mutation",
26169
26303
  access: "create"
@@ -33179,4 +33313,4 @@ function enumerateInferenceDevices(hw) {
33179
33313
  return out;
33180
33314
  }
33181
33315
  //#endregion
33182
- export { objectInputDeclaresAddonId as $, deviceManagerCapability as A, hydrateSchema as At, isCollectionArrayMethod as B, bareAddonId as C, asJsonObject as Ct, coreBlocksCapability as D, emitDownForOwnedCaps as Dt, coreBlockIdFromAddonId as E, createEvent as Et, enumerateItemArrayFields as F, readinessKey as Ft, lifecycleJobSchema as G, isSameAddonId as H, enumerateSchemaFields as I, resolveCapMount as It, logLevelAtMost as J, localNetworkCapability as K, extractNestedAddonId as L, scopeKey as Lt, deviceStatusCapability as M, nodePin as Mt, doorbellCapability as N, parseJsonObject as Nt, dataStoreProviderCapability as O, emitReadiness as Ot, enumerateInferenceDevices as P, parseJsonUnknown as Pt, oauthIntegrationCapability as Q, filesystemBrowseCapability as R, sleep as Rt, backupCapability as S, WELL_KNOWN_TAB_MAP as St, coreBlockAddonId as T, asString as Tt, isVoidInput as U, isObjectInput as V, kebabToCamel as W, metricsProviderCapability as X, looseSchema as Y, normalizeUnit as Z, addonPagesCapability as _, DeviceFeature as _t, CAP_NAMES_WITH_STATUS as a, snapshotCapability as at, alertsCapability as b, ReadinessRegistry as bt, CoreBlockSchema as c, streamQualityLabel as ct, METHOD_ACCESS_MAP as d, vectorStoreCapability as dt, parseStreamParamsFormPatch as et, RUNTIME_DEFAULTS as f, errMsg as ft, UserRecordSchema as g, DEVICE_STATUS_METHOD as gt, StorageLocationTypeSchema as h, DEVICE_SETTINGS_CONTRIBUTION_METHODS as ht, BatteryStatusSchema as i, settingsStoreCapability as it, deviceStateCapability as j, isDeviceConfigCap as jt, decodeVectorBase64 as k, expandCapMethods as kt, DeclaredDevices as l, userManagementCapability as lt, ScopedTokenSchema as m, DATAPLANE_SECRET_HEADER as mt, AlertSchema as n, procedureAuthKey as nt, CORE_BLOCKS_ADDON_ID as o, storageCapability as ot, STREAM_PROFILE_META as p, BaseAddon as pt, logDestinationCapability as q, ApiKeyRecordSchema as r, scoreRuntimes as rt, CORE_BLOCK_ADDON_PREFIX as s, storageProviderCapability as st, ALL_CAPABILITY_DEFINITIONS as t, platformProbeCapability as tt, DeviceStatusSchema as u, vectorDimFromBase64 as ut, addonSettingsCapability as v, DeviceRole as vt, buildStreamParamsConfigSchema as w, asNumber as wt, authProviderCapability as x, ReadinessTimeoutError as xt, addonWidgetsCapability as y, DeviceType as yt, isArrayOutputSchema as z, EventCategory as zt };
33316
+ export { parseStreamParamsFormPatch as $, deviceManagerCapability as A, expandCapMethods as At, isCollectionArrayMethod as B, EventCategory as Bt, bareAddonId as C, WELL_KNOWN_TAB_MAP as Ct, coreBlocksCapability as D, createEvent as Dt, coreBlockIdFromAddonId as E, asString as Et, enumerateItemArrayFields as F, parseJsonUnknown as Ft, lifecycleJobSchema as G, isSameAddonId as H, enumerateSchemaFields as I, readinessKey as It, logLevelAtMost as J, localNetworkCapability as K, extractNestedAddonId as L, resolveCapMount as Lt, deviceStatusCapability as M, isDeviceConfigCap as Mt, doorbellCapability as N, nodePin as Nt, dataStoreProviderCapability as O, emitDownForOwnedCaps as Ot, enumerateInferenceDevices as P, parseJsonObject as Pt, objectInputDeclaresAddonId as Q, filesystemBrowseCapability as R, scopeKey as Rt, backupCapability as S, ReadinessTimeoutError as St, coreBlockAddonId as T, asNumber as Tt, isVoidInput as U, isObjectInput as V, kebabToCamel as W, metricsProviderCapability as X, looseSchema as Y, normalizeUnit as Z, addonPagesCapability as _, DEVICE_STATUS_METHOD as _t, CAP_NAMES_WITH_STATUS as a, settingsStoreCapability as at, alertsCapability as b, DeviceType as bt, CoreBlockSchema as c, storageProviderCapability as ct, METHOD_ACCESS_MAP as d, vectorDimFromBase64 as dt, platformProbeCapability as et, RUNTIME_DEFAULTS as f, vectorStoreCapability as ft, UserRecordSchema as g, DEVICE_SETTINGS_CONTRIBUTION_METHODS as gt, StorageLocationTypeSchema as h, DATAPLANE_SECRET_HEADER as ht, BatteryStatusSchema as i, scoreRuntimes as it, deviceStateCapability as j, hydrateSchema as jt, decodeVectorBase64 as k, emitReadiness as kt, DeclaredDevices as l, streamQualityLabel as lt, ScopedTokenSchema as m, BaseAddon as mt, AlertSchema as n, scopesAllowAddon as nt, CORE_BLOCKS_ADDON_ID as o, snapshotCapability as ot, STREAM_PROFILE_META as p, errMsg as pt, logDestinationCapability as q, ApiKeyRecordSchema as r, scopesAllowDeviceCap as rt, CORE_BLOCK_ADDON_PREFIX as s, storageCapability as st, ALL_CAPABILITY_DEFINITIONS as t, procedureAuthKey as tt, DeviceStatusSchema as u, userManagementCapability as ut, addonSettingsCapability as v, DeviceFeature as vt, buildStreamParamsConfigSchema as w, asJsonObject as wt, authProviderCapability as x, ReadinessRegistry as xt, addonWidgetsCapability as y, DeviceRole as yt, isArrayOutputSchema as z, sleep as zt };