@camstack/addon-auth 1.2.146 → 1.2.147

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.
@@ -12327,6 +12327,13 @@ function parseAppAuthCallback(raw) {
12327
12327
  */
12328
12328
  /** What the app redeems the code for. `step-up` yields a proof, never a session. */
12329
12329
  var AppFlowPurposeSchema = _enum(["new-session", "step-up"]);
12330
+ /** The languages the hub's app landing pages are written in (D858). */
12331
+ var AppPageLangSchema = _enum(["en", "it"]);
12332
+ /** Narrows an untrusted `lang` value to the allow-list; anything else is `undefined`, never echoed. */
12333
+ function parseAppPageLang(value) {
12334
+ const parsed = AppPageLangSchema.safeParse(value);
12335
+ return parsed.success ? parsed.data : void 0;
12336
+ }
12330
12337
  /** Where the app is sent when the request names no `redirect`. */
12331
12338
  var APP_FLOW_DEFAULT_REDIRECT = "camstack://auth-callback";
12332
12339
  /** S256 challenge: base64url of 32 bytes = 43 characters, no padding. */
@@ -12343,7 +12350,8 @@ var STATE_PATTERN = /^[A-Za-z0-9._~-]{1,256}$/;
12343
12350
  var APP_REFUSED_PATH = "/auth/app/refused";
12344
12351
  /**
12345
12352
  * Read the app parameters off a start query: `code_challenge`,
12346
- * `code_challenge_method`, `state`, `purpose`, `redirect`. Anything missing or
12353
+ * `code_challenge_method`, `state`, `purpose`, `redirect`, and the optional `lang` (an unknown value is
12354
+ * dropped, not refused). Anything missing or
12347
12355
  * malformed is refused - there is no lenient default for PKCE or state.
12348
12356
  */
12349
12357
  function parseAppFlowRequest(query) {
@@ -12372,13 +12380,15 @@ function parseAppFlowRequest(query) {
12372
12380
  ok: false,
12373
12381
  reason: "bad-redirect"
12374
12382
  };
12383
+ const lang = parseAppPageLang(query["lang"]);
12375
12384
  return {
12376
12385
  ok: true,
12377
12386
  request: {
12378
12387
  codeChallenge: challenge,
12379
12388
  state,
12380
12389
  purpose: purpose.data,
12381
- redirect
12390
+ redirect,
12391
+ ...lang !== void 0 ? { lang } : {}
12382
12392
  }
12383
12393
  };
12384
12394
  }
@@ -49957,7 +49967,9 @@ var SsoBridgeClaimsSchema = object({
49957
49967
  codeChallenge: string(),
49958
49968
  state: string(),
49959
49969
  purpose: _enum(["new-session", "step-up"]),
49960
- redirect: string()
49970
+ redirect: string(),
49971
+ /** The page language the app asked for (D858); the confirm page speaks it. */
49972
+ lang: _enum(["en", "it"]).optional()
49961
49973
  }).optional()
49962
49974
  });
49963
49975
  method(object({
@@ -59356,6 +59368,21 @@ DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
59356
59368
  on: boolean(),
59357
59369
  lastChangedAt: number()
59358
59370
  });
59371
+ /** C0 controls, DEL and the C1 range: none of them belongs in a name. */
59372
+ function hasControlCharacter(value) {
59373
+ for (const char of value) {
59374
+ const code = char.codePointAt(0) ?? 0;
59375
+ if (code <= 31 || code >= 127 && code <= 159) return true;
59376
+ }
59377
+ return false;
59378
+ }
59379
+ string().transform((value) => value.trim()).pipe(string().min(1, "The server name cannot be empty").max(48, `The server name is at most 48 characters`).refine((value) => !hasControlCharacter(value), { message: "The server name cannot contain control characters" }));
59380
+ /** What every reader gets: the name to show, and whether the hub chose it itself. */
59381
+ var ServerNameInfoSchema = object({
59382
+ name: string(),
59383
+ /** `true` when nobody named the hub: `name` is the machine hostname. */
59384
+ isDefault: boolean()
59385
+ });
59359
59386
  /**
59360
59387
  * system — system-scoped singleton capability exposing hub-level
59361
59388
  * health, feature flags, network interface enumeration, and the
@@ -59385,6 +59412,12 @@ var FeatureManifestSchema = object({
59385
59412
  backup: boolean(),
59386
59413
  repl: boolean()
59387
59414
  });
59415
+ /**
59416
+ * `system.info`: the feature flags plus the hub's human name (D861). The name is
59417
+ * `{ name, isDefault }` — `isDefault: true` means nobody named the hub and `name`
59418
+ * is the machine hostname.
59419
+ */
59420
+ var SystemInfoSchema = FeatureManifestSchema.extend({ serverName: ServerNameInfoSchema });
59388
59421
  var HealthStatusSchema = object({
59389
59422
  status: literal("ok"),
59390
59423
  uptime: number()
@@ -59857,7 +59890,7 @@ var LoggingSettingsStateSchema = object({
59857
59890
  opsLogRetentionDays: number().int().min(0),
59858
59891
  persisted: boolean()
59859
59892
  });
59860
- method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
59893
+ method(_void(), SystemInfoSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
59861
59894
  kind: "mutation",
59862
59895
  auth: "admin"
59863
59896
  }), method(_void(), _void(), {
@@ -72892,4 +72925,4 @@ DEFAULT_NATIVE_LEASE_SETTINGS.admission;
72892
72925
  var MB = 1024 * 1024;
72893
72926
  1024 * MB, 3072 * MB;
72894
72927
  //#endregion
72895
- export { object as A, globalSecretScope as C, array as D, toSecretFieldView as E, boolean as O, arrayItemFieldPath as S, isSecretMarker as T, resolveIconKey as _, addonWidgetsSourceCapability as a, BaseAddon as b, authProviderCapability as c, loginMethodCapability as d, normalizeOrigin as f, requestMountPrefix as g, pickRequestOrigin as h, addonRoutesCapability as i, string as j, number as k, buildAddonRouteProvider as l, parseAppFlowRequest as m, APP_REFUSED_PATH as n, advertisedHubOrigins as o, oidcConnectionsCapability as p, SSO_STATE_COOKIE as r, appFlowLocation as s, APP_FLOW_DEFAULT_REDIRECT as t, claimedRequestOrigins as u, userPasskeysCapability as v, isSecretClear as w, SECRET_CLEAR as x, errMsg as y };
72928
+ export { number as A, arrayItemFieldPath as C, toSecretFieldView as D, isSecretMarker as E, string as M, array as O, SECRET_CLEAR as S, isSecretClear as T, requestMountPrefix as _, addonWidgetsSourceCapability as a, errMsg as b, authProviderCapability as c, loginMethodCapability as d, normalizeOrigin as f, pickRequestOrigin as g, parseAppPageLang as h, addonRoutesCapability as i, object as j, boolean as k, buildAddonRouteProvider as l, parseAppFlowRequest as m, APP_REFUSED_PATH as n, advertisedHubOrigins as o, oidcConnectionsCapability as p, SSO_STATE_COOKIE as r, appFlowLocation as s, APP_FLOW_DEFAULT_REDIRECT as t, claimedRequestOrigins as u, resolveIconKey as v, globalSecretScope as w, BaseAddon as x, userPasskeysCapability as y };
@@ -12361,6 +12361,13 @@ function parseAppAuthCallback(raw) {
12361
12361
  */
12362
12362
  /** What the app redeems the code for. `step-up` yields a proof, never a session. */
12363
12363
  var AppFlowPurposeSchema = _enum(["new-session", "step-up"]);
12364
+ /** The languages the hub's app landing pages are written in (D858). */
12365
+ var AppPageLangSchema = _enum(["en", "it"]);
12366
+ /** Narrows an untrusted `lang` value to the allow-list; anything else is `undefined`, never echoed. */
12367
+ function parseAppPageLang(value) {
12368
+ const parsed = AppPageLangSchema.safeParse(value);
12369
+ return parsed.success ? parsed.data : void 0;
12370
+ }
12364
12371
  /** Where the app is sent when the request names no `redirect`. */
12365
12372
  var APP_FLOW_DEFAULT_REDIRECT = "camstack://auth-callback";
12366
12373
  /** S256 challenge: base64url of 32 bytes = 43 characters, no padding. */
@@ -12377,7 +12384,8 @@ var STATE_PATTERN = /^[A-Za-z0-9._~-]{1,256}$/;
12377
12384
  var APP_REFUSED_PATH = "/auth/app/refused";
12378
12385
  /**
12379
12386
  * Read the app parameters off a start query: `code_challenge`,
12380
- * `code_challenge_method`, `state`, `purpose`, `redirect`. Anything missing or
12387
+ * `code_challenge_method`, `state`, `purpose`, `redirect`, and the optional `lang` (an unknown value is
12388
+ * dropped, not refused). Anything missing or
12381
12389
  * malformed is refused - there is no lenient default for PKCE or state.
12382
12390
  */
12383
12391
  function parseAppFlowRequest(query) {
@@ -12406,13 +12414,15 @@ function parseAppFlowRequest(query) {
12406
12414
  ok: false,
12407
12415
  reason: "bad-redirect"
12408
12416
  };
12417
+ const lang = parseAppPageLang(query["lang"]);
12409
12418
  return {
12410
12419
  ok: true,
12411
12420
  request: {
12412
12421
  codeChallenge: challenge,
12413
12422
  state,
12414
12423
  purpose: purpose.data,
12415
- redirect
12424
+ redirect,
12425
+ ...lang !== void 0 ? { lang } : {}
12416
12426
  }
12417
12427
  };
12418
12428
  }
@@ -49991,7 +50001,9 @@ var SsoBridgeClaimsSchema = object({
49991
50001
  codeChallenge: string(),
49992
50002
  state: string(),
49993
50003
  purpose: _enum(["new-session", "step-up"]),
49994
- redirect: string()
50004
+ redirect: string(),
50005
+ /** The page language the app asked for (D858); the confirm page speaks it. */
50006
+ lang: _enum(["en", "it"]).optional()
49995
50007
  }).optional()
49996
50008
  });
49997
50009
  method(object({
@@ -59390,6 +59402,21 @@ DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
59390
59402
  on: boolean(),
59391
59403
  lastChangedAt: number()
59392
59404
  });
59405
+ /** C0 controls, DEL and the C1 range: none of them belongs in a name. */
59406
+ function hasControlCharacter(value) {
59407
+ for (const char of value) {
59408
+ const code = char.codePointAt(0) ?? 0;
59409
+ if (code <= 31 || code >= 127 && code <= 159) return true;
59410
+ }
59411
+ return false;
59412
+ }
59413
+ string().transform((value) => value.trim()).pipe(string().min(1, "The server name cannot be empty").max(48, `The server name is at most 48 characters`).refine((value) => !hasControlCharacter(value), { message: "The server name cannot contain control characters" }));
59414
+ /** What every reader gets: the name to show, and whether the hub chose it itself. */
59415
+ var ServerNameInfoSchema = object({
59416
+ name: string(),
59417
+ /** `true` when nobody named the hub: `name` is the machine hostname. */
59418
+ isDefault: boolean()
59419
+ });
59393
59420
  /**
59394
59421
  * system — system-scoped singleton capability exposing hub-level
59395
59422
  * health, feature flags, network interface enumeration, and the
@@ -59419,6 +59446,12 @@ var FeatureManifestSchema = object({
59419
59446
  backup: boolean(),
59420
59447
  repl: boolean()
59421
59448
  });
59449
+ /**
59450
+ * `system.info`: the feature flags plus the hub's human name (D861). The name is
59451
+ * `{ name, isDefault }` — `isDefault: true` means nobody named the hub and `name`
59452
+ * is the machine hostname.
59453
+ */
59454
+ var SystemInfoSchema = FeatureManifestSchema.extend({ serverName: ServerNameInfoSchema });
59422
59455
  var HealthStatusSchema = object({
59423
59456
  status: literal("ok"),
59424
59457
  uptime: number()
@@ -59891,7 +59924,7 @@ var LoggingSettingsStateSchema = object({
59891
59924
  opsLogRetentionDays: number().int().min(0),
59892
59925
  persisted: boolean()
59893
59926
  });
59894
- method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
59927
+ method(_void(), SystemInfoSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
59895
59928
  kind: "mutation",
59896
59929
  auth: "admin"
59897
59930
  }), method(_void(), _void(), {
@@ -73106,6 +73139,12 @@ Object.defineProperty(exports, "parseAppFlowRequest", {
73106
73139
  return parseAppFlowRequest;
73107
73140
  }
73108
73141
  });
73142
+ Object.defineProperty(exports, "parseAppPageLang", {
73143
+ enumerable: true,
73144
+ get: function() {
73145
+ return parseAppPageLang;
73146
+ }
73147
+ });
73109
73148
  Object.defineProperty(exports, "pickRequestOrigin", {
73110
73149
  enumerable: true,
73111
73150
  get: function() {
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-DtqB-MTf.js");
5
+ const require_dist = require("../dist-DDdB_Mme.js");
6
6
  let node_crypto = require("node:crypto");
7
7
  node_crypto = require_dist.__toESM(node_crypto);
8
8
  //#region ../../node_modules/jose/dist/webapi/lib/buffer_utils.js
@@ -1411,7 +1411,8 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
1411
1411
  const reason = parsed.ok ? "combined-flow" : parsed.reason;
1412
1412
  reply.code(303);
1413
1413
  reply.header("Cache-Control", "no-store");
1414
- reply.header("Location", `${require_dist.APP_REFUSED_PATH}?reason=${reason}`);
1414
+ const lang = require_dist.parseAppPageLang(query["lang"]);
1415
+ reply.header("Location", `${require_dist.APP_REFUSED_PATH}?reason=${reason}${lang !== void 0 ? `&lang=${lang}` : ""}`);
1415
1416
  reply.send("");
1416
1417
  return;
1417
1418
  }
@@ -1524,7 +1525,8 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
1524
1525
  codeChallenge: result.app.codeChallenge,
1525
1526
  state: result.app.state,
1526
1527
  purpose: result.app.purpose,
1527
- redirect: result.app.redirect
1528
+ redirect: result.app.redirect,
1529
+ ...result.app.lang !== void 0 ? { lang: result.app.lang } : {}
1528
1530
  } } : {}
1529
1531
  } });
1530
1532
  const finish = new URLSearchParams({ bridge: bridgeToken });
@@ -1,4 +1,4 @@
1
- import { C as globalSecretScope, E as toSecretFieldView, S as arrayItemFieldPath, T as isSecretMarker, _ as resolveIconKey, b as BaseAddon, c as authProviderCapability, d as loginMethodCapability, f as normalizeOrigin, g as requestMountPrefix, h as pickRequestOrigin, i as addonRoutesCapability, l as buildAddonRouteProvider, m as parseAppFlowRequest, n as APP_REFUSED_PATH, o as advertisedHubOrigins, p as oidcConnectionsCapability, r as SSO_STATE_COOKIE, s as appFlowLocation, t as APP_FLOW_DEFAULT_REDIRECT, u as claimedRequestOrigins, w as isSecretClear, x as SECRET_CLEAR, y as errMsg } from "../dist-BtJOajm3.mjs";
1
+ import { C as arrayItemFieldPath, D as toSecretFieldView, E as isSecretMarker, S as SECRET_CLEAR, T as isSecretClear, _ as requestMountPrefix, b as errMsg, c as authProviderCapability, d as loginMethodCapability, f as normalizeOrigin, g as pickRequestOrigin, h as parseAppPageLang, i as addonRoutesCapability, l as buildAddonRouteProvider, m as parseAppFlowRequest, n as APP_REFUSED_PATH, o as advertisedHubOrigins, p as oidcConnectionsCapability, r as SSO_STATE_COOKIE, s as appFlowLocation, t as APP_FLOW_DEFAULT_REDIRECT, u as claimedRequestOrigins, v as resolveIconKey, w as globalSecretScope, x as BaseAddon } from "../dist-BGsjH-S3.mjs";
2
2
  import * as crypto$1 from "node:crypto";
3
3
  //#region ../../node_modules/jose/dist/webapi/lib/buffer_utils.js
4
4
  var encoder = new TextEncoder(), decoder = new TextDecoder(), strictDecoder = new TextDecoder("utf-8", { fatal: !0 });
@@ -1406,7 +1406,8 @@ var AuthOidcAddon = class extends BaseAddon {
1406
1406
  const reason = parsed.ok ? "combined-flow" : parsed.reason;
1407
1407
  reply.code(303);
1408
1408
  reply.header("Cache-Control", "no-store");
1409
- reply.header("Location", `${APP_REFUSED_PATH}?reason=${reason}`);
1409
+ const lang = parseAppPageLang(query["lang"]);
1410
+ reply.header("Location", `${APP_REFUSED_PATH}?reason=${reason}${lang !== void 0 ? `&lang=${lang}` : ""}`);
1410
1411
  reply.send("");
1411
1412
  return;
1412
1413
  }
@@ -1519,7 +1520,8 @@ var AuthOidcAddon = class extends BaseAddon {
1519
1520
  codeChallenge: result.app.codeChallenge,
1520
1521
  state: result.app.state,
1521
1522
  purpose: result.app.purpose,
1522
- redirect: result.app.redirect
1523
+ redirect: result.app.redirect,
1524
+ ...result.app.lang !== void 0 ? { lang: result.app.lang } : {}
1523
1525
  } } : {}
1524
1526
  } });
1525
1527
  const finish = new URLSearchParams({ bridge: bridgeToken });
@@ -18,7 +18,7 @@ var e = {
18
18
  },
19
19
  "@camstack/types": {
20
20
  name: "@camstack/types",
21
- version: "1.2.372",
21
+ version: "1.2.373",
22
22
  scope: ["default"],
23
23
  loaded: !1,
24
24
  from: "addon_auth_webauthn_widgets",
@@ -33,7 +33,7 @@ var e = {
33
33
  },
34
34
  "@camstack/ui-library": {
35
35
  name: "@camstack/ui-library",
36
- version: "1.2.290",
36
+ version: "1.2.291",
37
37
  scope: ["default"],
38
38
  loaded: !1,
39
39
  from: "addon_auth_webauthn_widgets",
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-DtqB-MTf.js");
5
+ const require_dist = require("../dist-DDdB_Mme.js");
6
6
  let stream = require("stream");
7
7
  stream = require_dist.__toESM(stream, 1);
8
8
  let http = require("http");
@@ -1,4 +1,4 @@
1
- import { A as object, D as array, O as boolean, a as addonWidgetsSourceCapability, b as BaseAddon, d as loginMethodCapability, j as string, k as number, v as userPasskeysCapability } from "../dist-BtJOajm3.mjs";
1
+ import { A as number, M as string, O as array, a as addonWidgetsSourceCapability, d as loginMethodCapability, j as object, k as boolean, x as BaseAddon, y as userPasskeysCapability } from "../dist-BGsjH-S3.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import Stream from "stream";
4
4
  import http from "http";
@@ -36,7 +36,7 @@ async function r() {
36
36
  }
37
37
  },
38
38
  "@camstack/types": {
39
- version: "1.2.372",
39
+ version: "1.2.373",
40
40
  scope: "default",
41
41
  shareConfig: {
42
42
  singleton: !0,
@@ -81,7 +81,7 @@ async function r() {
81
81
  }
82
82
  },
83
83
  "@camstack/ui-library": {
84
- version: "1.2.290",
84
+ version: "1.2.291",
85
85
  scope: "default",
86
86
  shareConfig: {
87
87
  singleton: !0,
@@ -30,7 +30,7 @@ async function d(e) {
30
30
  }
31
31
  }
32
32
  async function f() {
33
- return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_auth_webauthn_widgets-C3_j2tlC.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_auth_webauthn_widgets-DiKn9eAB.mjs")).catch((e) => {
34
34
  throw l = void 0, e;
35
35
  }), l;
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-auth",
3
- "version": "1.2.146",
3
+ "version": "1.2.147",
4
4
  "description": "Authentication bundle — OIDC and WebAuthn/passkey. Multi-entry npm package shipping 2 addons under a single bundle; each addon keeps its own id, capabilities, and runner.",
5
5
  "keywords": [
6
6
  "camstack",