@camstack/addon-import-alexa 0.2.167 → 0.2.168
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/CHANGELOG.md +6 -0
- package/dist/addon.js +81 -8
- package/dist/addon.mjs +81 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.168] - 2026-10-29
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Alexa sign-in trace now records the proxy's first request to Amazon (parameter names and whether OAuth parameters are present) and the browser family, to diagnose logins that end without an authorization code.
|
|
15
|
+
|
|
10
16
|
## [0.2.167] - 2026-10-29
|
|
11
17
|
|
|
12
18
|
### Changed
|
package/dist/addon.js
CHANGED
|
@@ -55191,11 +55191,13 @@ var ImageContractSchema = object({
|
|
|
55191
55191
|
* The shell verdict (see {@link WrapperKindSchema}) with the proofs that
|
|
55192
55192
|
* produced it.
|
|
55193
55193
|
*
|
|
55194
|
-
* There is deliberately NO `canSelfUpdate`
|
|
55195
|
-
*
|
|
55196
|
-
*
|
|
55197
|
-
*
|
|
55198
|
-
*
|
|
55194
|
+
* There is deliberately NO `canSelfUpdate` boolean: a wrapper update is an
|
|
55195
|
+
* ANNOUNCEMENT. The notification body carries the exact command for a `docker`
|
|
55196
|
+
* shell and says the app restarts into the new build for `electron`, and that
|
|
55197
|
+
* sentence is chosen from `kind` alone — a boolean nothing reads is the defect
|
|
55198
|
+
* this repo keeps paying for. The one shell that CAN be acted on is the
|
|
55199
|
+
* Electron app, and only through `installDesktopUpdate` (see
|
|
55200
|
+
* {@link DesktopAppStatusSchema} for what the node reads from the app first).
|
|
55199
55201
|
*/
|
|
55200
55202
|
var WrapperIdentitySchema = object({
|
|
55201
55203
|
kind: _enum([
|
|
@@ -55243,6 +55245,49 @@ var ServerRollbackInfoSchema = object({
|
|
|
55243
55245
|
reason: string()
|
|
55244
55246
|
});
|
|
55245
55247
|
/**
|
|
55248
|
+
* What the native desktop app (Electron) that hosts this node says about
|
|
55249
|
+
* itself, read from `<dataDir>/server-root/desktop-app-state.json` (ADR-0971).
|
|
55250
|
+
* Absent on the status = no desktop app, or it never wrote the file.
|
|
55251
|
+
*
|
|
55252
|
+
* `stale` is the honest answer to an app that stopped writing (closed, hung,
|
|
55253
|
+
* crashed): the update facts are then the LAST ones known, not current ones,
|
|
55254
|
+
* and a consumer must not read `update.available: false` from a stale record
|
|
55255
|
+
* as "no update". `stateAtMs` is when the app last wrote.
|
|
55256
|
+
*/
|
|
55257
|
+
var DesktopAppStatusSchema = object({
|
|
55258
|
+
/** The Electron app's own version (not the node closure's). */
|
|
55259
|
+
version: string(),
|
|
55260
|
+
update: object({
|
|
55261
|
+
available: boolean(),
|
|
55262
|
+
/** The new build is downloaded and `installDesktopUpdate` can apply it. */
|
|
55263
|
+
downloaded: boolean(),
|
|
55264
|
+
version: string().nullable(),
|
|
55265
|
+
checking: boolean(),
|
|
55266
|
+
/** Why the app's last update check produced no answer; `null` when it did. */
|
|
55267
|
+
error: string().nullable()
|
|
55268
|
+
}),
|
|
55269
|
+
stateAtMs: number(),
|
|
55270
|
+
stale: boolean()
|
|
55271
|
+
});
|
|
55272
|
+
/**
|
|
55273
|
+
* Why `installDesktopUpdate` did nothing. Stable names a UI maps to a sentence:
|
|
55274
|
+
* - `not-electron` — this node does not run inside the desktop app.
|
|
55275
|
+
* - `no-app-state` — the app never published its state (or the file is unreadable).
|
|
55276
|
+
* - `app-state-stale` — the app stopped writing; it is probably not running.
|
|
55277
|
+
* - `not-downloaded` — no update is downloaded yet; nothing to install.
|
|
55278
|
+
*/
|
|
55279
|
+
var InstallDesktopUpdateReasonSchema = _enum([
|
|
55280
|
+
"not-electron",
|
|
55281
|
+
"no-app-state",
|
|
55282
|
+
"app-state-stale",
|
|
55283
|
+
"not-downloaded"
|
|
55284
|
+
]);
|
|
55285
|
+
var InstallDesktopUpdateResultSchema = object({
|
|
55286
|
+
accepted: boolean(),
|
|
55287
|
+
/** Non-null exactly when `accepted` is false. */
|
|
55288
|
+
reason: InstallDesktopUpdateReasonSchema.nullable()
|
|
55289
|
+
});
|
|
55290
|
+
/**
|
|
55246
55291
|
* The runner boot check (D877): the runners this node PLANNED (hub: one per
|
|
55247
55292
|
* `resolveRunnerId` over its forked addons; agent: the runners its process
|
|
55248
55293
|
* service holds, because only the hub plans) against the states the process
|
|
@@ -55346,7 +55391,12 @@ var ServerPackageStatusSchema = object({
|
|
|
55346
55391
|
* on a provider that predates it. Absent is "not checked yet", never "all
|
|
55347
55392
|
* well": a consumer that needs the answer treats it as pending.
|
|
55348
55393
|
*/
|
|
55349
|
-
runners: RunnerBootCheckSchema.optional()
|
|
55394
|
+
runners: RunnerBootCheckSchema.optional(),
|
|
55395
|
+
/**
|
|
55396
|
+
* The desktop app hosting this node (see {@link DesktopAppStatusSchema}).
|
|
55397
|
+
* Optional for version skew AND because most nodes have no desktop app.
|
|
55398
|
+
*/
|
|
55399
|
+
desktopApp: DesktopAppStatusSchema.optional()
|
|
55350
55400
|
});
|
|
55351
55401
|
var ServerUpdateCheckResultSchema = object({
|
|
55352
55402
|
packageName: string(),
|
|
@@ -55451,6 +55501,9 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
|
|
|
55451
55501
|
kind: "mutation",
|
|
55452
55502
|
auth: "admin",
|
|
55453
55503
|
timeoutMs: 16 * 6e4
|
|
55504
|
+
}), method(_void(), InstallDesktopUpdateResultSchema, {
|
|
55505
|
+
kind: "mutation",
|
|
55506
|
+
auth: "admin"
|
|
55454
55507
|
}), method(_void(), ServerUpdateActionResultSchema, {
|
|
55455
55508
|
kind: "mutation",
|
|
55456
55509
|
auth: "admin"
|
|
@@ -81212,6 +81265,13 @@ Object.freeze({
|
|
|
81212
81265
|
access: "view",
|
|
81213
81266
|
role: "admin"
|
|
81214
81267
|
},
|
|
81268
|
+
"serverManagement.installDesktopUpdate": {
|
|
81269
|
+
capName: "server-management",
|
|
81270
|
+
capScope: "system",
|
|
81271
|
+
addonId: null,
|
|
81272
|
+
access: "create",
|
|
81273
|
+
role: "admin"
|
|
81274
|
+
},
|
|
81215
81275
|
"serverManagement.restartServer": {
|
|
81216
81276
|
capName: "server-management",
|
|
81217
81277
|
capScope: "system",
|
|
@@ -134100,7 +134160,9 @@ function formatUrlParams(url) {
|
|
|
134100
134160
|
* redirect target — always WITHOUT a query string or fragment. Any line that is
|
|
134101
134161
|
* not one of the known step lines yields `null` and is never traced.
|
|
134102
134162
|
*/
|
|
134103
|
-
var ROUTER_RE = /^Router: (\S+) \/ ([A-Z]+)
|
|
134163
|
+
var ROUTER_RE = /^Router: (\S+) \/ ([A-Z]+) \/ (.*)$/;
|
|
134164
|
+
var INITIAL_REQUEST_RE = /^Alexa-Cookie: Initial Page Request: (\S+)$/;
|
|
134165
|
+
var USER_AGENT_RE = /"user-agent":"([^"]*)"/i;
|
|
134104
134166
|
var PROXY_REQUEST_RE = /^Alexa-Cookie: Proxy-Request: ([A-Z]+) (\S+)$/;
|
|
134105
134167
|
var PROXY_RESPONSE_RE = /^Alexa-Cookie: Proxy Response from Host: (\S+)$/;
|
|
134106
134168
|
var REDIRECT_ORIGINAL_RE = /^Redirect: Original Location ----> (\S+)$/;
|
|
@@ -134114,9 +134176,20 @@ function stripQuery(target) {
|
|
|
134114
134176
|
function withParams(target) {
|
|
134115
134177
|
return `${stripQuery(target)} ${formatUrlParams(target)}`;
|
|
134116
134178
|
}
|
|
134179
|
+
/** Browser family of the header block's user-agent; the string itself is never kept. */
|
|
134180
|
+
function userAgentFamily(headers) {
|
|
134181
|
+
const ua = USER_AGENT_RE.exec(headers)?.[1];
|
|
134182
|
+
if (ua === void 0) return "none";
|
|
134183
|
+
if (/CriOS|Chrome|Chromium|Edg\//.test(ua)) return "chrome";
|
|
134184
|
+
if (/Firefox|FxiOS/.test(ua)) return "firefox";
|
|
134185
|
+
if (/Safari/.test(ua)) return "safari";
|
|
134186
|
+
return "other";
|
|
134187
|
+
}
|
|
134117
134188
|
function sanitizeProxyTraceLine(line) {
|
|
134118
134189
|
const router = ROUTER_RE.exec(line);
|
|
134119
|
-
if (router !== null) return `router ${router[2]} ${withParams(router[1] ?? "")}`;
|
|
134190
|
+
if (router !== null) return `router ${router[2]} ${withParams(router[1] ?? "")} ua=${userAgentFamily(router[3] ?? "")}`;
|
|
134191
|
+
const initial = INITIAL_REQUEST_RE.exec(line);
|
|
134192
|
+
if (initial !== null) return `initial-request ${withParams(initial[1] ?? "")}`;
|
|
134120
134193
|
const request = PROXY_REQUEST_RE.exec(line);
|
|
134121
134194
|
if (request !== null) return `proxy-request ${request[1]} ${withParams(request[2] ?? "")}`;
|
|
134122
134195
|
const response = PROXY_RESPONSE_RE.exec(line);
|
package/dist/addon.mjs
CHANGED
|
@@ -55190,11 +55190,13 @@ var ImageContractSchema = object({
|
|
|
55190
55190
|
* The shell verdict (see {@link WrapperKindSchema}) with the proofs that
|
|
55191
55191
|
* produced it.
|
|
55192
55192
|
*
|
|
55193
|
-
* There is deliberately NO `canSelfUpdate`
|
|
55194
|
-
*
|
|
55195
|
-
*
|
|
55196
|
-
*
|
|
55197
|
-
*
|
|
55193
|
+
* There is deliberately NO `canSelfUpdate` boolean: a wrapper update is an
|
|
55194
|
+
* ANNOUNCEMENT. The notification body carries the exact command for a `docker`
|
|
55195
|
+
* shell and says the app restarts into the new build for `electron`, and that
|
|
55196
|
+
* sentence is chosen from `kind` alone — a boolean nothing reads is the defect
|
|
55197
|
+
* this repo keeps paying for. The one shell that CAN be acted on is the
|
|
55198
|
+
* Electron app, and only through `installDesktopUpdate` (see
|
|
55199
|
+
* {@link DesktopAppStatusSchema} for what the node reads from the app first).
|
|
55198
55200
|
*/
|
|
55199
55201
|
var WrapperIdentitySchema = object({
|
|
55200
55202
|
kind: _enum([
|
|
@@ -55242,6 +55244,49 @@ var ServerRollbackInfoSchema = object({
|
|
|
55242
55244
|
reason: string()
|
|
55243
55245
|
});
|
|
55244
55246
|
/**
|
|
55247
|
+
* What the native desktop app (Electron) that hosts this node says about
|
|
55248
|
+
* itself, read from `<dataDir>/server-root/desktop-app-state.json` (ADR-0971).
|
|
55249
|
+
* Absent on the status = no desktop app, or it never wrote the file.
|
|
55250
|
+
*
|
|
55251
|
+
* `stale` is the honest answer to an app that stopped writing (closed, hung,
|
|
55252
|
+
* crashed): the update facts are then the LAST ones known, not current ones,
|
|
55253
|
+
* and a consumer must not read `update.available: false` from a stale record
|
|
55254
|
+
* as "no update". `stateAtMs` is when the app last wrote.
|
|
55255
|
+
*/
|
|
55256
|
+
var DesktopAppStatusSchema = object({
|
|
55257
|
+
/** The Electron app's own version (not the node closure's). */
|
|
55258
|
+
version: string(),
|
|
55259
|
+
update: object({
|
|
55260
|
+
available: boolean(),
|
|
55261
|
+
/** The new build is downloaded and `installDesktopUpdate` can apply it. */
|
|
55262
|
+
downloaded: boolean(),
|
|
55263
|
+
version: string().nullable(),
|
|
55264
|
+
checking: boolean(),
|
|
55265
|
+
/** Why the app's last update check produced no answer; `null` when it did. */
|
|
55266
|
+
error: string().nullable()
|
|
55267
|
+
}),
|
|
55268
|
+
stateAtMs: number(),
|
|
55269
|
+
stale: boolean()
|
|
55270
|
+
});
|
|
55271
|
+
/**
|
|
55272
|
+
* Why `installDesktopUpdate` did nothing. Stable names a UI maps to a sentence:
|
|
55273
|
+
* - `not-electron` — this node does not run inside the desktop app.
|
|
55274
|
+
* - `no-app-state` — the app never published its state (or the file is unreadable).
|
|
55275
|
+
* - `app-state-stale` — the app stopped writing; it is probably not running.
|
|
55276
|
+
* - `not-downloaded` — no update is downloaded yet; nothing to install.
|
|
55277
|
+
*/
|
|
55278
|
+
var InstallDesktopUpdateReasonSchema = _enum([
|
|
55279
|
+
"not-electron",
|
|
55280
|
+
"no-app-state",
|
|
55281
|
+
"app-state-stale",
|
|
55282
|
+
"not-downloaded"
|
|
55283
|
+
]);
|
|
55284
|
+
var InstallDesktopUpdateResultSchema = object({
|
|
55285
|
+
accepted: boolean(),
|
|
55286
|
+
/** Non-null exactly when `accepted` is false. */
|
|
55287
|
+
reason: InstallDesktopUpdateReasonSchema.nullable()
|
|
55288
|
+
});
|
|
55289
|
+
/**
|
|
55245
55290
|
* The runner boot check (D877): the runners this node PLANNED (hub: one per
|
|
55246
55291
|
* `resolveRunnerId` over its forked addons; agent: the runners its process
|
|
55247
55292
|
* service holds, because only the hub plans) against the states the process
|
|
@@ -55345,7 +55390,12 @@ var ServerPackageStatusSchema = object({
|
|
|
55345
55390
|
* on a provider that predates it. Absent is "not checked yet", never "all
|
|
55346
55391
|
* well": a consumer that needs the answer treats it as pending.
|
|
55347
55392
|
*/
|
|
55348
|
-
runners: RunnerBootCheckSchema.optional()
|
|
55393
|
+
runners: RunnerBootCheckSchema.optional(),
|
|
55394
|
+
/**
|
|
55395
|
+
* The desktop app hosting this node (see {@link DesktopAppStatusSchema}).
|
|
55396
|
+
* Optional for version skew AND because most nodes have no desktop app.
|
|
55397
|
+
*/
|
|
55398
|
+
desktopApp: DesktopAppStatusSchema.optional()
|
|
55349
55399
|
});
|
|
55350
55400
|
var ServerUpdateCheckResultSchema = object({
|
|
55351
55401
|
packageName: string(),
|
|
@@ -55450,6 +55500,9 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
|
|
|
55450
55500
|
kind: "mutation",
|
|
55451
55501
|
auth: "admin",
|
|
55452
55502
|
timeoutMs: 16 * 6e4
|
|
55503
|
+
}), method(_void(), InstallDesktopUpdateResultSchema, {
|
|
55504
|
+
kind: "mutation",
|
|
55505
|
+
auth: "admin"
|
|
55453
55506
|
}), method(_void(), ServerUpdateActionResultSchema, {
|
|
55454
55507
|
kind: "mutation",
|
|
55455
55508
|
auth: "admin"
|
|
@@ -81211,6 +81264,13 @@ Object.freeze({
|
|
|
81211
81264
|
access: "view",
|
|
81212
81265
|
role: "admin"
|
|
81213
81266
|
},
|
|
81267
|
+
"serverManagement.installDesktopUpdate": {
|
|
81268
|
+
capName: "server-management",
|
|
81269
|
+
capScope: "system",
|
|
81270
|
+
addonId: null,
|
|
81271
|
+
access: "create",
|
|
81272
|
+
role: "admin"
|
|
81273
|
+
},
|
|
81214
81274
|
"serverManagement.restartServer": {
|
|
81215
81275
|
capName: "server-management",
|
|
81216
81276
|
capScope: "system",
|
|
@@ -134099,7 +134159,9 @@ function formatUrlParams(url) {
|
|
|
134099
134159
|
* redirect target — always WITHOUT a query string or fragment. Any line that is
|
|
134100
134160
|
* not one of the known step lines yields `null` and is never traced.
|
|
134101
134161
|
*/
|
|
134102
|
-
var ROUTER_RE = /^Router: (\S+) \/ ([A-Z]+)
|
|
134162
|
+
var ROUTER_RE = /^Router: (\S+) \/ ([A-Z]+) \/ (.*)$/;
|
|
134163
|
+
var INITIAL_REQUEST_RE = /^Alexa-Cookie: Initial Page Request: (\S+)$/;
|
|
134164
|
+
var USER_AGENT_RE = /"user-agent":"([^"]*)"/i;
|
|
134103
134165
|
var PROXY_REQUEST_RE = /^Alexa-Cookie: Proxy-Request: ([A-Z]+) (\S+)$/;
|
|
134104
134166
|
var PROXY_RESPONSE_RE = /^Alexa-Cookie: Proxy Response from Host: (\S+)$/;
|
|
134105
134167
|
var REDIRECT_ORIGINAL_RE = /^Redirect: Original Location ----> (\S+)$/;
|
|
@@ -134113,9 +134175,20 @@ function stripQuery(target) {
|
|
|
134113
134175
|
function withParams(target) {
|
|
134114
134176
|
return `${stripQuery(target)} ${formatUrlParams(target)}`;
|
|
134115
134177
|
}
|
|
134178
|
+
/** Browser family of the header block's user-agent; the string itself is never kept. */
|
|
134179
|
+
function userAgentFamily(headers) {
|
|
134180
|
+
const ua = USER_AGENT_RE.exec(headers)?.[1];
|
|
134181
|
+
if (ua === void 0) return "none";
|
|
134182
|
+
if (/CriOS|Chrome|Chromium|Edg\//.test(ua)) return "chrome";
|
|
134183
|
+
if (/Firefox|FxiOS/.test(ua)) return "firefox";
|
|
134184
|
+
if (/Safari/.test(ua)) return "safari";
|
|
134185
|
+
return "other";
|
|
134186
|
+
}
|
|
134116
134187
|
function sanitizeProxyTraceLine(line) {
|
|
134117
134188
|
const router = ROUTER_RE.exec(line);
|
|
134118
|
-
if (router !== null) return `router ${router[2]} ${withParams(router[1] ?? "")}`;
|
|
134189
|
+
if (router !== null) return `router ${router[2]} ${withParams(router[1] ?? "")} ua=${userAgentFamily(router[3] ?? "")}`;
|
|
134190
|
+
const initial = INITIAL_REQUEST_RE.exec(line);
|
|
134191
|
+
if (initial !== null) return `initial-request ${withParams(initial[1] ?? "")}`;
|
|
134119
134192
|
const request = PROXY_REQUEST_RE.exec(line);
|
|
134120
134193
|
if (request !== null) return `proxy-request ${request[1]} ${withParams(request[2] ?? "")}`;
|
|
134121
134194
|
const response = PROXY_RESPONSE_RE.exec(line);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-import-alexa",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.168",
|
|
4
4
|
"description": "Alexa device-import provider for CamStack — imports the smart-home devices in a user's Alexa account via the unofficial alexa-remote2 cookie/token client (the inverse of the Alexa exporter)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|