@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.
- package/dist/addon-runner.js +6 -6
- package/dist/addon-runner.mjs +3 -3
- package/dist/addon-utils.js +11 -11
- package/dist/addon-utils.mjs +1 -1
- package/dist/auth/auth-manager.d.ts +13 -29
- package/dist/auth/scope-matcher.d.ts +6 -5
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +3 -3
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +2 -2
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +3 -3
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +2 -2
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +8 -8
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +6 -6
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +3 -3
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/index.d.ts +0 -1
- package/dist/builtins/local-auth/index.js +0 -1
- package/dist/builtins/local-auth/index.mjs +2 -2
- package/dist/builtins/local-auth/local-auth.addon.js +4878 -4883
- package/dist/builtins/local-auth/local-auth.addon.mjs +4879 -4883
- package/dist/builtins/local-auth/oauth-grants.d.ts +15 -0
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +5 -5
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +4 -4
- package/dist/builtins/platform-probe/index.js +4 -4
- package/dist/builtins/platform-probe/index.mjs +3 -3
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +2 -2
- package/dist/builtins/snapshot/index.mjs +2 -2
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +4 -4
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +3 -3
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +3 -3
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +2 -2
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-C-QzFJ8v.mjs → dist-Daxx9CB0.mjs} +139 -5
- package/dist/{dist-D7wC-S4p.js → dist-I0WgqQQ-.js} +150 -10
- package/dist/{model-download-service-CTBHzORJ.mjs → file-data-plane-CuE_hBli.mjs} +848 -848
- package/dist/index.d.ts +73 -81
- package/dist/index.js +1302 -1278
- package/dist/index.mjs +1283 -1259
- package/dist/kernel/capability-registry.d.ts +26 -0
- package/dist/kernel/config-schema.d.ts +1 -1
- package/dist/kernel/transport/parent-unowned-call.d.ts +27 -0
- package/dist/{manifest-python-deps-Dz1ryHIN.mjs → manifest-python-deps-BdWxKNvu.mjs} +49 -47
- package/dist/{manifest-python-deps-BE6l8Y4W.js → manifest-python-deps-BqIpg0C7.js} +49 -47
- package/package.json +1 -4
- package/dist/builtins/local-auth/homeassistant-integration.d.ts +0 -7
- package/dist/{model-download-service-Caj1kaSi.js → file-data-plane-DUHPHa-Y.js} +847 -847
- package/dist/{resource-monitor-BkP504Vq.mjs → resource-monitor-BWmQ5i-o.mjs} +1 -1
- package/dist/{resource-monitor-DNNomR-i.js → resource-monitor-CdnzxBLP.js} +1 -1
|
@@ -4148,6 +4148,24 @@ var ConvertResultSchema = zod.z.object({
|
|
|
4148
4148
|
artifacts: zod.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 = zod.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 = zod.z.object({
|
|
13027
13115
|
/** Stable id used as the `integration=` query param, e.g. 'export-alexa'. */
|
|
@@ -13052,7 +13140,30 @@ var OauthIntegrationDescriptorSchema = zod.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: zod.z.string().optional()
|
|
13143
|
+
hubUrl: zod.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: zod.z.union([zod.z.number().int().positive(), zod.z.literal("never")]).optional()
|
|
13056
13167
|
});
|
|
13057
13168
|
var oauthIntegrationCapability = {
|
|
13058
13169
|
name: "oauth-integration",
|
|
@@ -17357,7 +17468,16 @@ var SsoBridgeClaimsSchema = zod.z.object({
|
|
|
17357
17468
|
codeChallenge: zod.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: zod.z.string().optional()
|
|
17471
|
+
sessionId: zod.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: zod.z.union([zod.z.number().int().positive(), zod.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(zod.z.object({
|
|
17369
17489
|
claims: SsoBridgeClaimsSchema,
|
|
17370
|
-
|
|
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: zod.z.union([zod.z.number().int().positive(), zod.z.literal("never")]).optional()
|
|
17371
17500
|
}), zod.z.object({ token: zod.z.string() })),
|
|
17372
17501
|
verifyBridgeToken: method(zod.z.object({ token: zod.z.string() }), SsoBridgeClaimsSchema.nullable())
|
|
17373
17502
|
}
|
|
@@ -26163,7 +26292,12 @@ var userManagementCapability = {
|
|
|
26163
26292
|
hubUrl: zod.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: zod.z.string().optional()
|
|
26295
|
+
codeChallenge: zod.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: zod.z.union([zod.z.number().int().positive(), zod.z.literal("never")]).optional()
|
|
26167
26301
|
}), zod.z.object({ code: zod.z.string() }), {
|
|
26168
26302
|
kind: "mutation",
|
|
26169
26303
|
access: "create"
|
|
@@ -33617,12 +33751,6 @@ Object.defineProperty(exports, "normalizeUnit", {
|
|
|
33617
33751
|
return normalizeUnit;
|
|
33618
33752
|
}
|
|
33619
33753
|
});
|
|
33620
|
-
Object.defineProperty(exports, "oauthIntegrationCapability", {
|
|
33621
|
-
enumerable: true,
|
|
33622
|
-
get: function() {
|
|
33623
|
-
return oauthIntegrationCapability;
|
|
33624
|
-
}
|
|
33625
|
-
});
|
|
33626
33754
|
Object.defineProperty(exports, "objectInputDeclaresAddonId", {
|
|
33627
33755
|
enumerable: true,
|
|
33628
33756
|
get: function() {
|
|
@@ -33677,6 +33805,18 @@ Object.defineProperty(exports, "scopeKey", {
|
|
|
33677
33805
|
return scopeKey;
|
|
33678
33806
|
}
|
|
33679
33807
|
});
|
|
33808
|
+
Object.defineProperty(exports, "scopesAllowAddon", {
|
|
33809
|
+
enumerable: true,
|
|
33810
|
+
get: function() {
|
|
33811
|
+
return scopesAllowAddon;
|
|
33812
|
+
}
|
|
33813
|
+
});
|
|
33814
|
+
Object.defineProperty(exports, "scopesAllowDeviceCap", {
|
|
33815
|
+
enumerable: true,
|
|
33816
|
+
get: function() {
|
|
33817
|
+
return scopesAllowDeviceCap;
|
|
33818
|
+
}
|
|
33819
|
+
});
|
|
33680
33820
|
Object.defineProperty(exports, "scoreRuntimes", {
|
|
33681
33821
|
enumerable: true,
|
|
33682
33822
|
get: function() {
|