@dbx-tools/tunnel 0.6.82 → 0.6.86

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/lib/src/portr.js CHANGED
@@ -14,9 +14,9 @@ import { writeFile } from "node:fs/promises";
14
14
  import os from "node:os";
15
15
  import { delimiter, join } from "node:path";
16
16
  import { promisify } from "node:util";
17
- import { bin } from "@dbx-tools/core";
18
- import { env, log } from "@dbx-tools/shared-core";
19
- import { PUBLIC_DOMAIN_ENV } from "./env.js";
17
+ import { bin, config } from "@dbx-tools/core";
18
+ import { log } from "@dbx-tools/shared-core";
19
+ import { TUNNEL_CONFIG } from "./_config.js";
20
20
  const logger = log.logger("tunnel:portr");
21
21
  const PORTR_VERSION = "1.0.15-sse.2";
22
22
  const PORTR_RELEASE_URL = `https://github.com/reggie-db/portr/releases/download/v${PORTR_VERSION}`;
@@ -30,8 +30,8 @@ const execFileAsync = promisify(execFile);
30
30
  */
31
31
  export function resolvePortrConfig(opts) {
32
32
  // PORTR_* is upstream portr's own namespace, so it keeps its name.
33
- const token = env.string(opts.token, "PORTR_TOKEN");
34
- const domain = env.string(opts.publicDomain, PUBLIC_DOMAIN_ENV);
33
+ const token = config.string(opts.token, "PORTR_TOKEN");
34
+ const domain = config.string(opts.publicDomain, "PUBLIC_DOMAIN", TUNNEL_CONFIG);
35
35
  if (!token)
36
36
  return undefined;
37
37
  let subdomain = opts.subdomain;
@@ -40,7 +40,7 @@ export function resolvePortrConfig(opts) {
40
40
  subdomain ??= domain.split(".")[0];
41
41
  server = domain.slice(domain.indexOf(".") + 1);
42
42
  }
43
- server ??= env.text("PORTR_SERVER") ?? undefined;
43
+ server ??= config.text("PORTR_SERVER");
44
44
  if (!subdomain || !server || server === domain)
45
45
  return undefined;
46
46
  return { subdomain, server, token, port: opts.port };
@@ -102,4 +102,4 @@ export async function startPortr(config, childEnv) {
102
102
  logger.info(`portr tunneling https://${config.subdomain}.${config.server} -> :${config.port}`);
103
103
  return spawn("portr", ["start"], { env: childEnv, stdio: "inherit" });
104
104
  }
105
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9ydHIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcG9ydHIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7R0FVRztBQUNILE9BQU8sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN6QixPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUM1QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXRDLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN0QyxPQUFPLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUU3QyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQzFDLE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQztBQUNyQyxNQUFNLGlCQUFpQixHQUFHLHlEQUF5RCxhQUFhLEVBQUUsQ0FBQztBQUNuRyxNQUFNLGlCQUFpQixHQUFHLFNBQVMsQ0FBQztBQUNwQyxNQUFNLGFBQWEsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7QUFnQjFDOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUFDLElBS2xDO0lBQ0MsbUVBQW1FO0lBQ25FLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztJQUNwRCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsaUJBQWlCLENBQUMs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QUFNLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQyxNQUFNLFFBQVEsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDL0YsT0FBTyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0FBQ3hFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIHBvcnRyIGluc3RhbGwsIGNvbmZpZywgYW5kIGxhdW5jaCBzdXBwb3J0IGZvciB0aGUgdHVubmVsIHJ1bnRpbWUuXG4gKlxuICogVGhlIGJpbmFyeSBhbmQgY29uZmlnIHVzZSBwb3J0cidzIGNvbnZlbnRpb25hbCBgJEhPTUUvLnBvcnRyYCB0cmVlLiBUaGVcbiAqIGluc3RhbGwgaXMgaWRlbXBvdGVudCAodGhlIGluc3RhbGxlciBza2lwcyBhbiBleGlzdGluZyBleGVjdXRhYmxlKS4gVGhlXG4gKiBjb25maWcgaXMgcmVuZGVyZWQgZnJvbSBgVFVOTkVMX1BVQkxJQ19ET01BSU5gXG4gKiAoYDxzdWJkb21haW4+LjxzZXJ2ZXI+YCkgKyBgUE9SVFJfVE9LRU5gIGFuZCBwb2ludHMgcG9ydHIgYXQgdGhlIFBVQkxJQyBwb3J0XG4gKiAodGhlIHByb3h5IGxpc3RlbnMgdGhlcmUpLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0IHsgZXhlY0ZpbGUsIHNwYXduIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgd3JpdGVGaWxlIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBvcyBmcm9tIFwibm9kZTpvc1wiO1xuaW1wb3J0IHsgZGVsaW1pdGVyLCBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgcHJvbWlzaWZ5IH0gZnJvbSBcIm5vZGU6dXRpbFwiO1xuXG5pbXBvcnQgeyBiaW4gfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgeyBlbnYsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBQVUJMSUNfRE9NQUlOX0VOViB9IGZyb20gXCIuL2Vudi50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsOnBvcnRyXCIpO1xuY29uc3QgUE9SVFJfVkVSU0lPTiA9IFwiMS4wLjE1LXNzZS4yXCI7XG5jb25zdCBQT1JUUl9SRUxFQVNFX1VSTCA9IGBodHRwczovL2dpdGh1Yi5jb20vcmVnZ2llLWRiL3BvcnRyL3JlbGVhc2VzL2Rvd25sb2FkL3Yke1BPUlRSX1ZFUlNJT059YDtcbmNvbnN0IFBPUlRSX01JTl9WRVJTSU9OID0gXCJ2MS4wLjE1XCI7XG5jb25zdCBleGVjRmlsZUFzeW5jID0gcHJvbWlzaWZ5KGV4ZWNGaWxlKTtcblxuLyoqIE9wdGlvbnMgZm9yIGluc3RhbGxpbmcgdGhlIHBvcnRyIGV4ZWN1dGFibGUuICovXG5leHBvcnQgaW50ZXJmYWNlIFBvcnRySW5zdGFsbE9wdGlvbnMge1xuICAvKiogSG9tZSBkaXJlY3RvcnkgY29udGFpbmluZyBgLnBvcnRyYDsgZGVmYXVsdHMgdG8gdGhlIE9TIGhvbWUgZGlyZWN0b3J5LiAqL1xuICBob21lRGlyPzogc3RyaW5nO1xufVxuXG4vKiogUmVzb2x2ZWQgcG9ydHIgd2lyaW5nLCBvciBgdW5kZWZpbmVkYCB3aGVuIG5vIHR1bm5lbCBpcyBjb25maWd1cmVkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQb3J0ckNvbmZpZyB7XG4gIHN1YmRvbWFpbjogc3RyaW5nO1xuICBzZXJ2ZXI6IHN0cmluZztcbiAgdG9rZW46IHN0cmluZztcbiAgcG9ydDogbnVtYmVyO1xufVxuXG4vKipcbiAqIFJlc29sdmUgcG9ydHIgY29uZmlnIGZyb20gYFRVTk5FTF9QVUJMSUNfRE9NQUlOYCArIGBQT1JUUl9UT0tFTmAsIG9yIGFuXG4gKiBleHBsaWNpdCBgc3ViZG9tYWluYC4gVGhlIGRvbWFpbiBpcyBgPHN1YmRvbWFpbj4uPHNlcnZlcj5gIChlLmcuXG4gKiBgZGVtby5hcHBzLmRieC50b29sc2ApLiBSZXR1cm5zIGB1bmRlZmluZWRgIChubyB0dW5uZWwpIHdoZW4gdGhlIHRva2VuIG9yIGFcbiAqIHVzYWJsZSBkb21haW4gaXMgYWJzZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVBvcnRyQ29uZmlnKG9wdHM6IHtcbiAgcHVibGljRG9tYWluPzogc3RyaW5nO1xuICBzdWJkb21haW4/OiBzdHJpbmc7XG4gIHRva2VuPzogc3RyaW5nO1xuICBwb3J0OiBudW1iZXI7XG59KTogUG9ydHJDb25maWcgfCB1bmRlZmluZWQge1xuICAvLyBQT1JUUl8qIGlzIHVwc3RyZWFtIHBvcnRyJ3Mgb3duIG5hbWVzcGFjZSwgc28gaXQga2VlcHMgaXRzIG5hbWUuXG4gIGNvbnN0IHRva2VuID0gZW52LnN0cmluZyhvcHRzLnRva2VuLCBcIlBPUlRSX1RPS0VOXCIpO1xuICBjb25zdCBkb21haW4gPSBlbnYuc3RyaW5nKG9wdHMucHVibGljRG9tYWluLCBQVUJMSUNfRE9NQUlOX0VOVik7XG4gIGlmICghdG9rZW4pIHJldHVybiB1bmRlZmluZWQ7XG4gIGxldCBzdWJkb21haW4gPSBvcHRzLnN1YmRvbWFpbjtcbiAgbGV0IHNlcnZlcjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBpZiAoZG9tYWluKSB7XG4gICAgc3ViZG9tYWluID8/PSBkb21haW4uc3BsaXQoXCIuXCIpWzBdO1xuICAgIHNlcnZlciA9IGRvbWFpbi5zbGljZShkb21haW4uaW5kZXhPZihcIi5cIikgKyAxKTtcbiAgfVxuICBzZXJ2ZXIgPz89IGVudi50ZXh0KFwiUE9SVFJfU0VSVkVSXCIpID8/IHVuZGVmaW5lZDtcbiAgaWYgKCFzdWJkb21haW4gfHwgIXNlcnZlciB8fCBzZXJ2ZXIgPT09IGRvbWFpbikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIHsgc3ViZG9tYWluLCBzZXJ2ZXIsIHRva2VuLCBwb3J0OiBvcHRzLnBvcnQgfTtcbn1cblxuLyoqIEdpdEh1YiByZWxlYXNlIGFzc2V0IG5hbWUgZm9yIHRoZSBjdXJyZW50IG9yIHN1cHBsaWVkIE9TL2FyY2hpdGVjdHVyZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwb3J0ckFzc2V0TmFtZShcbiAgdmVyc2lvbjogc3RyaW5nLFxuICBwbGF0Zm9ybTogTm9kZUpTLlBsYXRmb3JtID0gcHJvY2Vzcy5wbGF0Zm9ybSxcbiAgYXJjaDogc3RyaW5nID0gcHJvY2Vzcy5hcmNoLFxuKTogc3RyaW5nIHtcbiAgY29uc3Qgb3NOYW1lID0gcGxhdGZvcm0gPT09IFwiZGFyd2luXCIgPyBcIkRhcndpblwiIDogcGxhdGZvcm0gPT09IFwibGludXhcIiA/IFwiTGludXhcIiA6IHVuZGVmaW5lZDtcbiAgY29uc3QgYXJjaE5hbWUgPSBhcmNoID09PSBcImFybTY0XCIgPyBcImFybTY0XCIgOiBhcmNoID09PSBcIng2NFwiID8gXCJ4ODZfNjRcIiA6IHVuZGVmaW5lZDtcbiAgaWYgKCFvc05hbWUgfHwgIWFyY2hOYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBwb3J0ciBoYXMgbm8gc3VwcG9ydGVkIHJlbGVhc2UgYXNzZXQgZm9yICR7cGxhdGZvcm19LyR7YXJjaH1gKTtcbiAgfVxuICByZXR1cm4gYHBvcnRyXyR7dmVyc2lvbn1fJHtvc05hbWV9XyR7YXJjaE5hbWV9LnppcGA7XG59XG5cbmZ1bmN0aW9uIHBvcnRyRG93bmxvYWRVcmwoKTogc3RyaW5nIHtcbiAgY29uc3QgYXNzZXROYW1lID0gcG9ydHJBc3NldE5hbWUoUE9SVFJfVkVSU0lPTik7XG4gIGxvZ2dlci5pbmZvKFwiaW5zdGFsbGluZyBwb3J0clwiLCB7IHZlcnNpb246IFBPUlRSX1ZFUlNJT04sIGFzc2V0OiBhc3NldE5hbWUgfSk7XG4gIHJldHVybiBgJHtQT1JUUl9SRUxFQVNFX1VSTH0vJHthc3NldE5hbWV9YDtcbn1cblxuLyoqIEluc3RhbGwgcG9ydHIgd2hlbiBhYnNlbnQgYW5kIHJldHVybiB0aGUgZW52aXJvbm1lbnQgdXNlZCBieSBpdHMgcHJvY2Vzcy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsUG9ydHIob3B0aW9uczogUG9ydHJJbnN0YWxsT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxOb2RlSlMuUHJvY2Vzc0Vudj4ge1xuICBjb25zdCBob21lRGlyID0gb3B0aW9ucy5ob21lRGlyID8/IG9zLmhvbWVkaXIoKTtcbiAgY29uc3QgY29udGV4dCA9IGF3YWl0IGJpbi5lbnN1cmUoXCJwb3J0clwiLCBwb3J0ckRvd25sb2FkVXJsLCB7XG4gICAgYXV0b1VucGFja2FnZTogdHJ1ZSxcbiAgICBob21lRGlyLFxuICAgIG1pblZlcnNpb246IFBPUlRSX01JTl9WRVJTSU9OLFxuICAgIHNlbGVjdG9yOiAoeyBzb3VyY2UgfSkgPT4gam9pbihzb3VyY2UsIFwicG9ydHJcIiksXG4gICAgdmVyc2lvblBhcnNlcjogKG91dHB1dCkgPT4ge1xuICAgICAgY29uc3QgdmVyc2lvbiA9IGJpbi5wYXJzZVZlcnNpb24ob3V0cHV0KTtcbiAgICAgIHJldHVybiB2ZXJzaW9uID09PSBQT1JUUl9WRVJTSU9OID8gdmVyc2lvbiA6IHVuZGVmaW5lZDtcbiAgICB9LFxuICB9KTtcbiAgcmV0dXJuIHtcbiAgICAuLi5wcm9jZXNzLmVudixcbiAgICBIT01FOiBob21lRGlyLFxuICAgIFBPUlRSX0FVVE9fQUREX1BBVEg6IFwibm9cIixcbiAgICBQQVRIOiBbY29udGV4dC5iaW5EaXIsIHByb2Nlc3MuZW52LlBBVEggPz8gXCJcIl0uam9pbihkZWxpbWl0ZXIpLFxuICB9O1xufVxuXG4vKiogUmVuZGVyIGB+Ly5wb3J0ci9jb25maWcueWFtbGAgZm9yIHRoZSByZXNvbHZlZCB0dW5uZWwuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVQb3J0ckNvbmZpZyhcbiAgY29uZmlnOiBQb3J0ckNvbmZpZyxcbiAgY2hpbGRFbnY6IE5vZGVKUy5Qcm9jZXNzRW52LFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHBhdGggPSBqb2luKGNoaWxkRW52LkhPTUUgPz8gb3MuaG9tZWRpcigpLCBcIi5wb3J0clwiLCBcImNvbmZpZy55YW1sXCIpO1xuICBhd2FpdCB3cml0ZUZpbGUoXG4gICAgcGF0aCxcbiAgICBbXG4gICAgICBgc2VydmVyX3VybDogJHtjb25maWcuc2VydmVyfWAsXG4gICAgICBgc3NoX3VybDogJHtjb25maWcuc2VydmVyfTo0NDQ0YCxcbiAgICAgIGBzZWNyZXRfa2V5OiAke2NvbmZpZy50b2tlbn1gLFxuICAgICAgXCJkaXNhYmxlX2Rhc2hib2FyZDogdHJ1ZVwiLFxuICAgICAgXCJkaXNhYmxlX3R1aTogdHJ1ZVwiLFxuICAgICAgXCJ0dW5uZWxzOlwiLFxuICAgICAgYCAgLSBuYW1lOiAke2NvbmZpZy5zdWJkb21haW59YCxcbiAgICAgIGAgICAgc3ViZG9tYWluOiAke2NvbmZpZy5zdWJkb21haW59YCxcbiAgICAgIGAgICAgcG9ydDogJHtjb25maWcucG9ydH1gLFxuICAgICAgXCJcIixcbiAgICBdLmpvaW4oXCJcXG5cIiksXG4gICk7XG59XG5cbi8qKiBMYXVuY2ggYHBvcnRyIHN0YXJ0YCBhcyBhIGNoaWxkIHByb2Nlc3MgKGNhbGxlciBzdXBlcnZpc2VzICsga2lsbHMgaXQpLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YXJ0UG9ydHIoXG4gIGNvbmZpZzogUG9ydHJDb25maWcsXG4gIGNoaWxkRW52OiBOb2RlSlMuUHJvY2Vzc0Vudixcbik6IFByb21pc2U8UmV0dXJuVHlwZTx0eXBlb2Ygc3Bhd24+PiB7XG4gIC8vIFJlY2xhaW0gdGhlIHN1YmRvbWFpbiBmcm9tIGFueSBwb3J0ciBsZWZ0IGJ5IGEgcHJldmlvdXMgYm9vdCBpbiB0aGlzIGNvbnRhaW5lci5cbiAgYXdhaXQgZXhlY0ZpbGVBc3luYyhcInBraWxsXCIsIFtcIi14XCIsIFwicG9ydHJcIl0pLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG5cbiAgbG9nZ2VyLmluZm8oYHBvcnRyIHR1bm5lbGluZyBodHRwczovLyR7Y29uZmlnLnN1YmRvbWFpbn0uJHtjb25maWcuc2VydmVyfSAtPiA6JHtjb25maWcucG9ydH1gKTtcbiAgcmV0dXJuIHNwYXduKFwicG9ydHJcIiwgW1wic3RhcnRcIl0sIHsgZW52OiBjaGlsZEVudiwgc3RkaW86IFwiaW5oZXJpdFwiIH0pO1xufVxuIl19
105
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9ydHIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcG9ydHIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7R0FVRztBQUNILE9BQU8sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN6QixPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUM1QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXRDLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzdDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFN0MsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUMxQyxNQUFNLGFBQWEsR0FBRyxjQUFjLENBQUM7QUFDckMsTUFBTSxpQkFBaUIsR0FBRyx5REFBeUQsYUFBYSxFQUFFLENBQUM7QUFDbkcsTUFBTSxpQkFBaUIsR0FBRyxTQUFTLENBQUM7QUFDcEMsTUFBTSxhQUFhLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBZ0IxQzs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxJQUtsQztJQUNDLG1FQUFtRTtJQUNuRSxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDdkQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLGVBQWUsRUFBRSxhQUFh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Q0FBQyxTQUFTLElBQUksTUFBTSxDQUFDLE1BQU0sUUFBUSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMvRixPQUFPLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7QUFDeEUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogcG9ydHIgaW5zdGFsbCwgY29uZmlnLCBhbmQgbGF1bmNoIHN1cHBvcnQgZm9yIHRoZSB0dW5uZWwgcnVudGltZS5cbiAqXG4gKiBUaGUgYmluYXJ5IGFuZCBjb25maWcgdXNlIHBvcnRyJ3MgY29udmVudGlvbmFsIGAkSE9NRS8ucG9ydHJgIHRyZWUuIFRoZVxuICogaW5zdGFsbCBpcyBpZGVtcG90ZW50ICh0aGUgaW5zdGFsbGVyIHNraXBzIGFuIGV4aXN0aW5nIGV4ZWN1dGFibGUpLiBUaGVcbiAqIGNvbmZpZyBpcyByZW5kZXJlZCBmcm9tIGBUVU5ORUxfUFVCTElDX0RPTUFJTmBcbiAqIChgPHN1YmRvbWFpbj4uPHNlcnZlcj5gKSArIGBQT1JUUl9UT0tFTmAgYW5kIHBvaW50cyBwb3J0ciBhdCB0aGUgUFVCTElDIHBvcnRcbiAqICh0aGUgcHJveHkgbGlzdGVucyB0aGVyZSkuXG4gKlxuICogQG1vZHVsZVxuICovXG5pbXBvcnQgeyBleGVjRmlsZSwgc3Bhd24gfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgeyB3cml0ZUZpbGUgfSBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiO1xuaW1wb3J0IG9zIGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgeyBkZWxpbWl0ZXIsIGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tIFwibm9kZTp1dGlsXCI7XG5cbmltcG9ydCB7IGJpbiwgY29uZmlnIH0gZnJvbSBcIkBkYngtdG9vbHMvY29yZVwiO1xuaW1wb3J0IHsgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IFRVTk5FTF9DT05GSUcgfSBmcm9tIFwiLi9fY29uZmlnLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJ0dW5uZWw6cG9ydHJcIik7XG5jb25zdCBQT1JUUl9WRVJTSU9OID0gXCIxLjAuMTUtc3NlLjJcIjtcbmNvbnN0IFBPUlRSX1JFTEVBU0VfVVJMID0gYGh0dHBzOi8vZ2l0aHViLmNvbS9yZWdnaWUtZGIvcG9ydHIvcmVsZWFzZXMvZG93bmxvYWQvdiR7UE9SVFJfVkVSU0lPTn1gO1xuY29uc3QgUE9SVFJfTUlOX1ZFUlNJT04gPSBcInYxLjAuMTVcIjtcbmNvbnN0IGV4ZWNGaWxlQXN5bmMgPSBwcm9taXNpZnkoZXhlY0ZpbGUpO1xuXG4vKiogT3B0aW9ucyBmb3IgaW5zdGFsbGluZyB0aGUgcG9ydHIgZXhlY3V0YWJsZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9ydHJJbnN0YWxsT3B0aW9ucyB7XG4gIC8qKiBIb21lIGRpcmVjdG9yeSBjb250YWluaW5nIGAucG9ydHJgOyBkZWZhdWx0cyB0byB0aGUgT1MgaG9tZSBkaXJlY3RvcnkuICovXG4gIGhvbWVEaXI/OiBzdHJpbmc7XG59XG5cbi8qKiBSZXNvbHZlZCBwb3J0ciB3aXJpbmcsIG9yIGB1bmRlZmluZWRgIHdoZW4gbm8gdHVubmVsIGlzIGNvbmZpZ3VyZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIFBvcnRyQ29uZmlnIHtcbiAgc3ViZG9tYWluOiBzdHJpbmc7XG4gIHNlcnZlcjogc3RyaW5nO1xuICB0b2tlbjogc3RyaW5nO1xuICBwb3J0OiBudW1iZXI7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBwb3J0ciBjb25maWcgZnJvbSBgVFVOTkVMX1BVQkxJQ19ET01BSU5gICsgYFBPUlRSX1RPS0VOYCwgb3IgYW5cbiAqIGV4cGxpY2l0IGBzdWJkb21haW5gLiBUaGUgZG9tYWluIGlzIGA8c3ViZG9tYWluPi48c2VydmVyPmAgKGUuZy5cbiAqIGBkZW1vLmFwcHMuZGJ4LnRvb2xzYCkuIFJldHVybnMgYHVuZGVmaW5lZGAgKG5vIHR1bm5lbCkgd2hlbiB0aGUgdG9rZW4gb3IgYVxuICogdXNhYmxlIGRvbWFpbiBpcyBhYnNlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlUG9ydHJDb25maWcob3B0czoge1xuICBwdWJsaWNEb21haW4/OiBzdHJpbmc7XG4gIHN1YmRvbWFpbj86IHN0cmluZztcbiAgdG9rZW4/OiBzdHJpbmc7XG4gIHBvcnQ6IG51bWJlcjtcbn0pOiBQb3J0ckNvbmZpZyB8IHVuZGVmaW5lZCB7XG4gIC8vIFBPUlRSXyogaXMgdXBzdHJlYW0gcG9ydHIncyBvd24gbmFtZXNwYWNlLCBzbyBpdCBrZWVwcyBpdHMgbmFtZS5cbiAgY29uc3QgdG9rZW4gPSBjb25maWcuc3RyaW5nKG9wdHMudG9rZW4sIFwiUE9SVFJfVE9LRU5cIik7XG4gIGNvbnN0IGRvbWFpbiA9IGNvbmZpZy5zdHJpbmcob3B0cy5wdWJsaWNEb21haW4sIFwiUFVCTElDX0RPTUFJTlwiLCBUVU5ORUxfQ09ORklHKTtcbiAgaWYgKCF0b2tlbikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgbGV0IHN1YmRvbWFpbiA9IG9wdHMuc3ViZG9tYWluO1xuICBsZXQgc2VydmVyOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGlmIChkb21haW4pIHtcbiAgICBzdWJkb21haW4gPz89IGRvbWFpbi5zcGxpdChcIi5cIilbMF07XG4gICAgc2VydmVyID0gZG9tYWluLnNsaWNlKGRvbWFpbi5pbmRleE9mKFwiLlwiKSArIDEpO1xuICB9XG4gIHNlcnZlciA/Pz0gY29uZmlnLnRleHQoXCJQT1JUUl9TRVJWRVJcIik7XG4gIGlmICghc3ViZG9tYWluIHx8ICFzZXJ2ZXIgfHwgc2VydmVyID09PSBkb21haW4pIHJldHVybiB1bmRlZmluZWQ7XG4gIHJldHVybiB7IHN1YmRvbWFpbiwgc2VydmVyLCB0b2tlbiwgcG9ydDogb3B0cy5wb3J0IH07XG59XG5cbi8qKiBHaXRIdWIgcmVsZWFzZSBhc3NldCBuYW1lIGZvciB0aGUgY3VycmVudCBvciBzdXBwbGllZCBPUy9hcmNoaXRlY3R1cmUuICovXG5leHBvcnQgZnVuY3Rpb24gcG9ydHJBc3NldE5hbWUoXG4gIHZlcnNpb246IHN0cmluZyxcbiAgcGxhdGZvcm06IE5vZGVKUy5QbGF0Zm9ybSA9IHByb2Nlc3MucGxhdGZvcm0sXG4gIGFyY2g6IHN0cmluZyA9IHByb2Nlc3MuYXJjaCxcbik6IHN0cmluZyB7XG4gIGNvbnN0IG9zTmFtZSA9IHBsYXRmb3JtID09PSBcImRhcndpblwiID8gXCJEYXJ3aW5cIiA6IHBsYXRmb3JtID09PSBcImxpbnV4XCIgPyBcIkxpbnV4XCIgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IGFyY2hOYW1lID0gYXJjaCA9PT0gXCJhcm02NFwiID8gXCJhcm02NFwiIDogYXJjaCA9PT0gXCJ4NjRcIiA/IFwieDg2XzY0XCIgOiB1bmRlZmluZWQ7XG4gIGlmICghb3NOYW1lIHx8ICFhcmNoTmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgcG9ydHIgaGFzIG5vIHN1cHBvcnRlZCByZWxlYXNlIGFzc2V0IGZvciAke3BsYXRmb3JtfS8ke2FyY2h9YCk7XG4gIH1cbiAgcmV0dXJuIGBwb3J0cl8ke3ZlcnNpb259XyR7b3NOYW1lfV8ke2FyY2hOYW1lfS56aXBgO1xufVxuXG5mdW5jdGlvbiBwb3J0ckRvd25sb2FkVXJsKCk6IHN0cmluZyB7XG4gIGNvbnN0IGFzc2V0TmFtZSA9IHBvcnRyQXNzZXROYW1lKFBPUlRSX1ZFUlNJT04pO1xuICBsb2dnZXIuaW5mbyhcImluc3RhbGxpbmcgcG9ydHJcIiwgeyB2ZXJzaW9uOiBQT1JUUl9WRVJTSU9OLCBhc3NldDogYXNzZXROYW1lIH0pO1xuICByZXR1cm4gYCR7UE9SVFJfUkVMRUFTRV9VUkx9LyR7YXNzZXROYW1lfWA7XG59XG5cbi8qKiBJbnN0YWxsIHBvcnRyIHdoZW4gYWJzZW50IGFuZCByZXR1cm4gdGhlIGVudmlyb25tZW50IHVzZWQgYnkgaXRzIHByb2Nlc3MuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5zdGFsbFBvcnRyKG9wdGlvbnM6IFBvcnRySW5zdGFsbE9wdGlvbnMgPSB7fSk6IFByb21pc2U8Tm9kZUpTLlByb2Nlc3NFbnY+IHtcbiAgY29uc3QgaG9tZURpciA9IG9wdGlvbnMuaG9tZURpciA/PyBvcy5ob21lZGlyKCk7XG4gIGNvbnN0IGNvbnRleHQgPSBhd2FpdCBiaW4uZW5zdXJlKFwicG9ydHJcIiwgcG9ydHJEb3dubG9hZFVybCwge1xuICAgIGF1dG9VbnBhY2thZ2U6IHRydWUsXG4gICAgaG9tZURpcixcbiAgICBtaW5WZXJzaW9uOiBQT1JUUl9NSU5fVkVSU0lPTixcbiAgICBzZWxlY3RvcjogKHsgc291cmNlIH0pID0+IGpvaW4oc291cmNlLCBcInBvcnRyXCIpLFxuICAgIHZlcnNpb25QYXJzZXI6IChvdXRwdXQpID0+IHtcbiAgICAgIGNvbnN0IHZlcnNpb24gPSBiaW4ucGFyc2VWZXJzaW9uKG91dHB1dCk7XG4gICAgICByZXR1cm4gdmVyc2lvbiA9PT0gUE9SVFJfVkVSU0lPTiA/IHZlcnNpb24gOiB1bmRlZmluZWQ7XG4gICAgfSxcbiAgfSk7XG4gIHJldHVybiB7XG4gICAgLi4ucHJvY2Vzcy5lbnYsXG4gICAgSE9NRTogaG9tZURpcixcbiAgICBQT1JUUl9BVVRPX0FERF9QQVRIOiBcIm5vXCIsXG4gICAgUEFUSDogW2NvbnRleHQuYmluRGlyLCBwcm9jZXNzLmVudi5QQVRIID8/IFwiXCJdLmpvaW4oZGVsaW1pdGVyKSxcbiAgfTtcbn1cblxuLyoqIFJlbmRlciBgfi8ucG9ydHIvY29uZmlnLnlhbWxgIGZvciB0aGUgcmVzb2x2ZWQgdHVubmVsLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlUG9ydHJDb25maWcoXG4gIGNvbmZpZzogUG9ydHJDb25maWcsXG4gIGNoaWxkRW52OiBOb2RlSlMuUHJvY2Vzc0Vudixcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBwYXRoID0gam9pbihjaGlsZEVudi5IT01FID8/IG9zLmhvbWVkaXIoKSwgXCIucG9ydHJcIiwgXCJjb25maWcueWFtbFwiKTtcbiAgYXdhaXQgd3JpdGVGaWxlKFxuICAgIHBhdGgsXG4gICAgW1xuICAgICAgYHNlcnZlcl91cmw6ICR7Y29uZmlnLnNlcnZlcn1gLFxuICAgICAgYHNzaF91cmw6ICR7Y29uZmlnLnNlcnZlcn06NDQ0NGAsXG4gICAgICBgc2VjcmV0X2tleTogJHtjb25maWcudG9rZW59YCxcbiAgICAgIFwiZGlzYWJsZV9kYXNoYm9hcmQ6IHRydWVcIixcbiAgICAgIFwiZGlzYWJsZV90dWk6IHRydWVcIixcbiAgICAgIFwidHVubmVsczpcIixcbiAgICAgIGAgIC0gbmFtZTogJHtjb25maWcuc3ViZG9tYWlufWAsXG4gICAgICBgICAgIHN1YmRvbWFpbjogJHtjb25maWcuc3ViZG9tYWlufWAsXG4gICAgICBgICAgIHBvcnQ6ICR7Y29uZmlnLnBvcnR9YCxcbiAgICAgIFwiXCIsXG4gICAgXS5qb2luKFwiXFxuXCIpLFxuICApO1xufVxuXG4vKiogTGF1bmNoIGBwb3J0ciBzdGFydGAgYXMgYSBjaGlsZCBwcm9jZXNzIChjYWxsZXIgc3VwZXJ2aXNlcyArIGtpbGxzIGl0KS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydFBvcnRyKFxuICBjb25maWc6IFBvcnRyQ29uZmlnLFxuICBjaGlsZEVudjogTm9kZUpTLlByb2Nlc3NFbnYsXG4pOiBQcm9taXNlPFJldHVyblR5cGU8dHlwZW9mIHNwYXduPj4ge1xuICAvLyBSZWNsYWltIHRoZSBzdWJkb21haW4gZnJvbSBhbnkgcG9ydHIgbGVmdCBieSBhIHByZXZpb3VzIGJvb3QgaW4gdGhpcyBjb250YWluZXIuXG4gIGF3YWl0IGV4ZWNGaWxlQXN5bmMoXCJwa2lsbFwiLCBbXCIteFwiLCBcInBvcnRyXCJdKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuXG4gIGxvZ2dlci5pbmZvKGBwb3J0ciB0dW5uZWxpbmcgaHR0cHM6Ly8ke2NvbmZpZy5zdWJkb21haW59LiR7Y29uZmlnLnNlcnZlcn0gLT4gOiR7Y29uZmlnLnBvcnR9YCk7XG4gIHJldHVybiBzcGF3bihcInBvcnRyXCIsIFtcInN0YXJ0XCJdLCB7IGVudjogY2hpbGRFbnYsIHN0ZGlvOiBcImluaGVyaXRcIiB9KTtcbn1cbiJdfQ==
@@ -43,8 +43,9 @@
43
43
  */
44
44
  import { randomBytes } from "node:crypto";
45
45
  import { CacheManager } from "@databricks/appkit";
46
- import { env, log, object } from "@dbx-tools/shared-core";
47
- import { JWT_SECRET_ENV, SESSION_CUTOFF_ENV } from "./env.js";
46
+ import { config } from "@dbx-tools/core";
47
+ import { log, object } from "@dbx-tools/shared-core";
48
+ import { TUNNEL_CONFIG } from "./_config.js";
48
49
  const logger = log.logger("tunnel:signing-key");
49
50
  /**
50
51
  * How long a cached signing key lives: 30 days.
@@ -71,12 +72,14 @@ const KEY_BYTES = 32;
71
72
  * than not rotating.
72
73
  */
73
74
  export function resolveSessionCutoff(configured) {
74
- const raw = configured ?? env.text(SESSION_CUTOFF_ENV) ?? undefined;
75
+ const raw = configured ?? config.text(["AUTH_SESSION_CUTOFF", "AUTH_SESSION_EPOCH"], TUNNEL_CONFIG);
75
76
  if (raw === undefined || raw === null || raw === "")
76
77
  return 0;
77
78
  const date = object.toDate(raw);
78
79
  if (!date) {
79
- logger.warn(`ignoring unparseable ${env.name(SESSION_CUTOFF_ENV)}`, { value: String(raw) });
80
+ logger.warn(`ignoring unparseable ${config.name("AUTH_SESSION_CUTOFF", TUNNEL_CONFIG)}`, {
81
+ value: String(raw),
82
+ });
80
83
  return 0;
81
84
  }
82
85
  return clampToPast(date.getTime());
@@ -92,7 +95,7 @@ function clampToPast(cutoffMs) {
92
95
  const now = Date.now();
93
96
  if (cutoffMs <= now)
94
97
  return cutoffMs;
95
- logger.warn(`${env.name(SESSION_CUTOFF_ENV)} is in the future - clamping to now`, {
98
+ logger.warn(`${config.name("AUTH_SESSION_CUTOFF", TUNNEL_CONFIG)} is in the future - clamping to now`, {
96
99
  configured: new Date(cutoffMs).toISOString(),
97
100
  });
98
101
  return now;
@@ -149,7 +152,7 @@ let pending;
149
152
  export function signingKey(configuredCutoff) {
150
153
  pending ??= (async () => {
151
154
  const cutoffMs = resolveSessionCutoff(configuredCutoff);
152
- const configured = env.text(JWT_SECRET_ENV);
155
+ const configured = config.text("AUTH_JWT_SECRET", TUNNEL_CONFIG);
153
156
  if (configured) {
154
157
  return { key: new TextEncoder().encode(configured), cutoffMs };
155
158
  }
@@ -157,7 +160,7 @@ export function signingKey(configuredCutoff) {
157
160
  return { key: await loadFromCache(cutoffMs), cutoffMs };
158
161
  }
159
162
  catch (error) {
160
- logger.warn(`no ${env.name(JWT_SECRET_ENV)} and the cache is unavailable - using an ephemeral per-process key; sessions will not survive a restart`, { error });
163
+ logger.warn(`no ${config.name("AUTH_JWT_SECRET", TUNNEL_CONFIG)} and the cache is unavailable - using an ephemeral per-process key; sessions will not survive a restart`, { error });
161
164
  return { key: new Uint8Array(randomBytes(KEY_BYTES)), cutoffMs };
162
165
  }
163
166
  })();
@@ -167,4 +170,4 @@ export function signingKey(configuredCutoff) {
167
170
  export function resetSigningKey() {
168
171
  pending = undefined;
169
172
  }
170
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmluZy1rZXkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2lnbmluZy1rZXkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBDRztBQUVILE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDMUMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzFELE9BQU8sRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFOUQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0FBRWhEOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFFakQsa0ZBQWtGO0FBQ2xGLE1BQU0sVUFBVSxHQUFHLDBCQUEwQixDQUFDO0FBRTlDLGtGQUFrRjtBQUNsRixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUM7QUFVckI7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQUMsVUFBbUM7SUFDdEUsTUFBTSxHQUFHLEdBQUcsVUFBVSxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxTQUFTLENBQUM7SUFDcEUsSUFBSSxHQUFHLEtBQUssU0FBUyxJQUFJLEdBQUcsS0FBSyxJQUFJLElBQUksR0FBRyxLQUFLLEVBQUU7UUFBRSxPQUFPLENBQUMsQ0FBQztJQUU5RCxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2hDLElBQUksQ0FBQyxJQUFJLEVBQUUs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LE9BQU8sS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFO1FBQ3RCLE1BQU0sUUFBUSxHQUFHLG9CQUFvQixDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDeEQsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUM1QyxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2YsT0FBTyxFQUFFLEdBQUcsRUFBRSxJQUFJLFdBQVcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQztRQUNqRSxDQUFDO1FBQ0QsSUFBSSxDQUFDO1lBQ0gsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGFBQWEsQ0FBQyxRQUFRLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQztRQUMxRCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sQ0FBQyxJQUFJLENBQ1QsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyx5R0FBeUcsRUFDdkksRUFBRSxLQUFLLEVBQUUsQ0FDVixDQUFDO1lBQ0YsT0FBTyxFQUFFLEdBQUcsRUFBRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQztRQUNuRSxDQUFDO0lBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNMLE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsTUFBTSxVQUFVLGVBQWU7SUFDN0IsT0FBTyxHQUFHLFNBQVMsQ0FBQztBQUN0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgZ2F0ZSdzIEhTMjU2IHNlc3Npb24tc2lnbmluZyBrZXksIHBlcnNpc3RlZCBpbiBBcHBLaXQncyBjYWNoZS5cbiAqXG4gKiBUaGUga2V5IGRlY2lkZXMgd2hldGhlciBhIHNlc3Npb24gQ09PS0lFIHN0aWxsIHZlcmlmaWVzLCBzbyBpdCBtdXN0IE9VVExJVkUgdGhlXG4gKiBwcm9jZXNzOiBhIHBlci1wcm9jZXNzIGByYW5kb21CeXRlcygzMilgIHdvdWxkIGludmFsaWRhdGUgZXZlcnkgb3V0c3RhbmRpbmcgY29va2llXG4gKiBvbiByZXN0YXJ0IGFuZCBtYWtlIGVhY2ggc2lnbmVkLWluIHVzZXIgcmVxdWVzdCBhIG5ldyBjb2RlIC0gcGFpbmZ1bCBmb3IgYSB0dW5uZWwsXG4gKiB3aGljaCByZXN0YXJ0cyB3aGVuZXZlciB0aGUgYXBwIGl0IHdyYXBzIGRvZXMuIFNvIHRoZSBrZXkgaXMgc3RvcmVkIGluIHRoZSBjYWNoZVxuICogQXBwS2l0IGFscmVhZHkgY29uZmlndXJlZCAobWVtb3J5LCBvciBMYWtlYmFzZSB3aGVuIHRoZSBob3N0IHdpcmVzIGEgcGVyc2lzdGVudFxuICogYENhY2hlU3RvcmFnZWApLCBhbmQgd2l0aCBwZXJzaXN0ZW50IHN0b3JhZ2UgYSByZXN0YXJ0IGtlZXBzIHNlc3Npb25zIGFsaXZlIGZvclxuICoge0BsaW5rIEtFWV9UVExfU0VDT05EU30uXG4gKlxuICogQW4gZXhwbGljaXRseSBjb25maWd1cmVkIGBUVU5ORUxfQVVUSF9KV1RfU0VDUkVUYCBzdGlsbCB3aW5zIG91dHJpZ2h0LiBUaGF0IGlzXG4gKiB0aGUgcmlnaHQgYW5zd2VyIGZvciBhIGZsZWV0OiBhbiBvcGVyYXRvci1oZWxkIHNlY3JldCBuZWVkcyBubyBzaGFyZWQgY2FjaGUgYW5kXG4gKiBubyBjb252ZXJnZW5jZSwgYW5kIGl0IHN1cnZpdmVzIGEgY2FjaGUgZmx1c2guXG4gKlxuICogIyMgZ2V0IC8gZ2VuZXJhdGUgLyBnZXRcbiAqXG4gKiBUd28gaW5zdGFuY2VzIGJvb3RpbmcgYXQgb25jZSBib3RoIG1pc3MsIHNvIGJvdGggd291bGQgZ2VuZXJhdGUgLSBhbmQgdGhlIGxvc2VyXG4gKiB3b3VsZCBzaWduIGNvb2tpZXMgd2l0aCBhIGtleSB0aGUgd2lubmVyIHJlamVjdHMuIFJlc29sdXRpb24gaXMgYSByZS1SRUFEIGFmdGVyXG4gKiB0aGUgd3JpdGU6IHdoYXRldmVyIHRoZSBjYWNoZSBob2xkcyBhZnRlcndhcmRzIGlzIHRoZSBrZXkgZXZlcnlvbmUgYWRvcHRzLCBzb1xuICogdGhlIGluc3RhbmNlcyBjb252ZXJnZSBvbiBPTkUgdmFsdWUgaW5zdGVhZCBvZiB0cnVzdGluZyB0aGUgb25lIHRoZXkgbWludGVkLlxuICogKGBzZXRgIGlzIG5vdCBjb25kaXRpb25hbCBpbiB0aGUgY2FjaGUgQVBJIC0gdGhlcmUgaXMgbm8gYHNldG54YCB0byBsZWFuIG9uIC1cbiAqIGFuZCB0aGlzIHJ1bnMgb25jZSBwZXIgcHJvY2Vzcywgc28gdGhlIGV4dHJhIHJvdW5kLXRyaXAgaXMgZnJlZS4pXG4gKlxuICogQSBwYXRob2xvZ2ljYWwgaW50ZXJsZWF2ZSBjYW4gc3RpbGwgY29zdCBhIGtleTogaWYgQSB3cml0ZXMgYmV0d2VlbiBCJ3Mgd3JpdGVcbiAqIGFuZCBCJ3MgcmUtcmVhZCwgQiBhZG9wdHMgQSdzIGtleSB3aGlsZSBBIGFkb3B0cyBpdHMgb3duLiBUaGUgY29zdCBpcyBib3VuZGVkIC1cbiAqIGEgY29va2llIG1pbnRlZCBpbiB0aGF0IHdpbmRvdyBmYWlscyB0byB2ZXJpZnkgYW5kIHRoZSBob2xkZXIgc2lnbnMgaW4gYWdhaW4gLVxuICogYW5kIGl0IGNhbm5vdCBwcm9kdWNlIGEga2V5IG9uZSBpbnN0YW5jZSBUUlVTVFMgYnV0IGFub3RoZXIgcmVqZWN0cyBmb3IgbG9uZ2VyXG4gKiB0aGFuIHRoZSB3aW5kb3cgaXRzZWxmLiBTZXQgYFRVTk5FTF9BVVRIX0pXVF9TRUNSRVRgIHRvIHJlbW92ZSB0aGUgcmFjZVxuICogZW50aXJlbHkuXG4gKlxuICogIyMgRm9yY2luZyBldmVyeSBzZXNzaW9uIHRvIGVuZFxuICpcbiAqIHtAbGluayByZXNvbHZlU2Vzc2lvbkN1dG9mZn0gcmVhZHMgYSBkYXRlIGZyb20gYFRVTk5FTF9BVVRIX1NFU1NJT05fQ1VUT0ZGYCAob3JcbiAqIGAtLXNlc3Npb24tY3V0b2ZmYCksIGFuZCB0aGF0IGRhdGUgaXMgcGFydCBvZiB0aGUgY2FjaGUgS0VZLiBNb3ZpbmcgaXQgZm9yd2FyZFxuICogbWFrZXMgZXZlcnkgcHJpb3Iga2V5IHVucmVhY2hhYmxlLCBzbyBldmVyeSBjb29raWUgc2lnbmVkIGFnYWluc3QgaXQgc3RvcHNcbiAqIHZlcmlmeWluZyAtIHRoZSBsb2ctZXZlcnlvbmUtb3V0IHN3aXRjaCwgd2l0aG91dCBoYXZpbmcgdG8gZmluZCBhbmQgZmx1c2ggYVxuICogY2FjaGUgZW50cnkuIFRoZSBjdXRvZmYgaXMgYWxzbyBhc3NlcnRlZCBhZ2FpbnN0IGVhY2ggdG9rZW4ncyBgaWF0YCwgc28gYVxuICogY29va2llIHRoYXQgcHJlZGF0ZXMgaXQgaXMgcmVmdXNlZCBldmVuIGlmIGl0IHdhcyBzaWduZWQgd2l0aCB0aGUga2V5IHRoYXQgaXNcbiAqIHNvbWVob3cgc3RpbGwgY3VycmVudC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IENhY2hlTWFuYWdlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGVudiwgbG9nLCBvYmplY3QgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgSldUX1NFQ1JFVF9FTlYsIFNFU1NJT05fQ1VUT0ZGX0VOViB9IGZyb20gXCIuL2Vudi50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsOnNpZ25pbmcta2V5XCIpO1xuXG4vKipcbiAqIEhvdyBsb25nIGEgY2FjaGVkIHNpZ25pbmcga2V5IGxpdmVzOiAzMCBkYXlzLlxuICpcbiAqIFRoaXMgaXMgdGhlIGNlaWxpbmcgb24gaG93IGxvbmcgYSBzZXNzaW9uIGNvb2tpZSBjYW4gc3RheSB2YWxpZCBhY3Jvc3NcbiAqIHJlc3RhcnRzLCBzbyBpdCBpcyBkZWxpYmVyYXRlbHkgPj0gdGhlIGRlZmF1bHQgc2Vzc2lvbiBUVEwgLSBhIGtleSB0aGF0IGV4cGlyZWRcbiAqIGJlZm9yZSB0aGUgY29va2llcyBpdCBzaWduZWQgd291bGQgbG9nIGV2ZXJ5b25lIG91dCBmb3Igbm8gcmVhc29uLlxuICovXG5leHBvcnQgY29uc3QgS0VZX1RUTF9TRUNPTkRTID0gMzAgKiAyNCAqIDYwICogNjA7XG5cbi8qKiBDYWNoZS1rZXkgcHJlZml4IGZvciB0aGUgc2lnbmluZyBrZXksIG5hbWVzcGFjZWQgYXdheSBmcm9tIG90aGVyIGNhY2hlIHVzZS4gKi9cbmNvbnN0IEtFWV9QUkVGSVggPSBcInR1bm5lbDphdXRoOnNpZ25pbmcta2V5OlwiO1xuXG4vKiogQnl0ZXMgb2YgZW50cm9weSBpbiBhIGdlbmVyYXRlZCBrZXkgKDI1Ni1iaXQsIG1hdGNoaW5nIEhTMjU2J3MgaGFzaCB3aWR0aCkuICovXG5jb25zdCBLRVlfQllURVMgPSAzMjtcblxuLyoqIFdoYXQgdGhlIGNhY2hlIHN0b3JlczogdGhlIGtleSBwbHVzIHdoZW4gaXQgd2FzIG1pbnRlZCwgZm9yIG9ic2VydmFiaWxpdHkuICovXG5pbnRlcmZhY2UgU3RvcmVkS2V5IHtcbiAgLyoqIEJhc2U2NHVybCBvZiB0aGUgcmF3IGtleSBieXRlcy4gKi9cbiAgc2VjcmV0OiBzdHJpbmc7XG4gIC8qKiBXaGVuIHRoaXMga2V5IHdhcyBnZW5lcmF0ZWQsIElTTy04NjAxLiAqL1xuICBjcmVhdGVkQXQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBmb3JjZS1jbGVhciBjdXRvZmYgYXMgZXBvY2ggTUlMTElTRUNPTkRTLCBvciBgMGAgd2hlbiB1bnNldC5cbiAqXG4gKiBBY2NlcHRzIHdoYXRldmVyIGBvYmplY3QudG9EYXRlYCBhY2NlcHRzIC0gYSBgRGF0ZWAsIGAyMDI2LTA4LTAyYCwgYW4gSVNPXG4gKiBpbnN0YW50LCBlcG9jaCBzZWNvbmRzIG9yIG1pbGxpcyBmcm9tIGBkYXRlICslc2AsIG9yIGEgcmVsYXRpdmUgZHVyYXRpb25cbiAqIChgLTMwZGAsIGA3IGRheXMgYWdvYCksIHdoaWNoIGlzIHRoZSBzcGVsbGluZyBhbiBvcGVyYXRvciByZWFjaGluZyBmb3IgdGhpc1xuICogdXN1YWxseSB3YW50czogc2lnbiBvdXQgZXZlcnlvbmUgd2hvIHNpZ25lZCBpbiBtb3JlIHRoYW4gYSBtb250aCBhZ28uXG4gKlxuICogQW4gVU5QQVJTRUFCTEUgdmFsdWUgaXMgaWdub3JlZCB3aXRoIGEgd2FybmluZyByYXRoZXIgdGhhbiB0aHJvd2luZzogdGhpcyBpc1xuICogdGhlIHN3aXRjaCB0aGF0IGxvZ3MgYSBmbGVldCBiYWNrIGluLCBhbmQgZmFpbGluZyB0byBib290IG92ZXIgYSB0eXBvIGlzIHdvcnNlXG4gKiB0aGFuIG5vdCByb3RhdGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTZXNzaW9uQ3V0b2ZmKGNvbmZpZ3VyZWQ/OiBzdHJpbmcgfCBudW1iZXIgfCBEYXRlKTogbnVtYmVyIHtcbiAgY29uc3QgcmF3ID0gY29uZmlndXJlZCA/PyBlbnYudGV4dChTRVNTSU9OX0NVVE9GRl9FTlYpID8/IHVuZGVmaW5lZDtcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gbnVsbCB8fCByYXcgPT09IFwiXCIpIHJldHVybiAwO1xuXG4gIGNvbnN0IGRhdGUgPSBvYmplY3QudG9EYXRlKHJhdyk7XG4gIGlmICghZGF0ZSkge1xuICAgIGxvZ2dlci53YXJuKGBpZ25vcmluZyB1bnBhcnNlYWJsZSAke2Vudi5uYW1lKFNFU1NJT05fQ1VUT0ZGX0VOVil9YCwgeyB2YWx1ZTogU3RyaW5nKHJhdykgfSk7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgcmV0dXJuIGNsYW1wVG9QYXN0KGRhdGUuZ2V0VGltZSgpKTtcbn1cblxuLyoqXG4gKiBIb2xkIHRoZSBjdXRvZmYgYXQgXCJub3dcIiwgYmVjYXVzZSBhIEZVVFVSRSBjdXRvZmYgd291bGQgcmVmdXNlIHRoZSBzZXNzaW9ucyBpdFxuICogaXMgYWJvdXQgdG8gbWludCBhcyB3ZWxsIGFzIHRoZSBvbGQgb25lcyAtIGFuIGFwcCBub2JvZHkgY2FuIHNpZ24gaW4gdG8sIGZyb20gYVxuICogbWlzdHlwZWQgeWVhciwgd2l0aCB0aGUgZml4IGhpZGRlbiBiZWhpbmQgdW5kZXJzdGFuZGluZyB0aGlzIGZsYWcuIENsYW1wZWQsIGFcbiAqIGZ1dHVyZSBkYXRlIG1lYW5zIHdoYXQgYW4gb3BlcmF0b3Igc2V0dGluZyBpdCBhbHdheXMgbWVhbnQ6IGNsZWFyIGV2ZXJ5dGhpbmdcbiAqIG91dHN0YW5kaW5nLCB0aGVuIGNhcnJ5IG9uLlxuICovXG5mdW5jdGlvbiBjbGFtcFRvUGFzdChjdXRvZmZNczogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgaWYgKGN1dG9mZk1zIDw9IG5vdykgcmV0dXJuIGN1dG9mZk1zO1xuICBsb2dnZXIud2FybihgJHtlbnYubmFtZShTRVNTSU9OX0NVVE9GRl9FTlYpfSBpcyBpbiB0aGUgZnV0dXJlIC0gY2xhbXBpbmcgdG8gbm93YCwge1xuICAgIGNvbmZpZ3VyZWQ6IG5ldyBEYXRlKGN1dG9mZk1zKS50b0lTT1N0cmluZygpLFxuICB9KTtcbiAgcmV0dXJuIG5vdztcbn1cblxuLyoqIFRoZSBjYWNoZSBrZXkgZm9yIG9uZSBjdXRvZmYsIHNvIG1vdmluZyB0aGUgY3V0b2ZmIG9ycGhhbnMgZXZlcnkgZWFybGllciBrZXkuICovXG5mdW5jdGlvbiBjYWNoZUtleShjdXRvZmZNczogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke0tFWV9QUkVGSVh9JHtjdXRvZmZNc31gO1xufVxuXG5mdW5jdGlvbiBkZWNvZGUoc3RvcmVkOiBTdG9yZWRLZXkpOiBVaW50OEFycmF5IHtcbiAgcmV0dXJuIG5ldyBVaW50OEFycmF5KEJ1ZmZlci5mcm9tKHN0b3JlZC5zZWNyZXQsIFwiYmFzZTY0dXJsXCIpKTtcbn1cblxuLyoqXG4gKiBMb2FkIHRoZSBzaWduaW5nIGtleSBmb3IgYGN1dG9mZk1zYCBmcm9tIHRoZSBjYWNoZSwgbWludGluZyBhbmQgc3RvcmluZyBvbmVcbiAqIHdoZW4gYWJzZW50LiBTZWUgdGhlIG1vZHVsZSBkb2NzIGZvciB3aHkgdGhlIHdyaXRlIGlzIGZvbGxvd2VkIGJ5IGEgcmUtcmVhZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbG9hZEZyb21DYWNoZShjdXRvZmZNczogbnVtYmVyKTogUHJvbWlzZTxVaW50OEFycmF5PiB7XG4gIGNvbnN0IGNhY2hlID0gQ2FjaGVNYW5hZ2VyLmdldEluc3RhbmNlU3luYygpO1xuICBjb25zdCBrZXkgPSBjYWNoZUtleShjdXRvZmZNcyk7XG5cbiAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBjYWNoZS5nZXQ8U3RvcmVkS2V5PihrZXkpO1xuICBpZiAoZXhpc3Rpbmc/LnNlY3JldCkge1xuICAgIGxvZ2dlci5pbmZvKFwicmV1c2luZyBjYWNoZWQgc2lnbmluZyBrZXlcIiwgeyBjcmVhdGVkQXQ6IGV4aXN0aW5nLmNyZWF0ZWRBdCB9KTtcbiAgICByZXR1cm4gZGVjb2RlKGV4aXN0aW5nKTtcbiAgfVxuXG4gIGNvbnN0IG1pbnRlZDogU3RvcmVkS2V5ID0ge1xuICAgIHNlY3JldDogQnVmZmVyLmZyb20ocmFuZG9tQnl0ZXMoS0VZX0JZVEVTKSkudG9TdHJpbmcoXCJiYXNlNjR1cmxcIiksXG4gICAgY3JlYXRlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gIH07XG4gIGF3YWl0IGNhY2hlLnNldChrZXksIG1pbnRlZCwgeyB0dGw6IEtFWV9UVExfU0VDT05EUyB9KTtcblxuICAvLyBSZS1yZWFkIHJhdGhlciB0aGFuIHRydXN0aW5nIGBtaW50ZWRgOiBhbm90aGVyIGluc3RhbmNlIHRoYXQgcmFjZWQgdGhpcyBib290XG4gIC8vIG1heSBoYXZlIHdyaXR0ZW4gZmlyc3QsIGFuZCBhZG9wdGluZyB3aGF0ZXZlciBpcyBzdG9yZWQgaXMgd2hhdCBtYWtlcyB0aGUgdHdvXG4gIC8vIGNvbnZlcmdlIG9uIG9uZSBrZXkuXG4gIGNvbnN0IHNldHRsZWQgPSAoYXdhaXQgY2FjaGUuZ2V0PFN0b3JlZEtleT4oa2V5KSkgPz8gbWludGVkO1xuICBsb2dnZXIuaW5mbyhcInN0b3JlZCBhIG5ldyBzaWduaW5nIGtleVwiLCB7XG4gICAgY3JlYXRlZEF0OiBzZXR0bGVkLmNyZWF0ZWRBdCxcbiAgICB0dGxTZWNvbmRzOiBLRVlfVFRMX1NFQ09ORFMsXG4gICAgYWRvcHRlZDogc2V0dGxlZC5jcmVhdGVkQXQgPT09IG1pbnRlZC5jcmVhdGVkQXQgPyBcIm93blwiIDogXCJjb25jdXJyZW50LWluc3RhbmNlXCIsXG4gIH0pO1xuICByZXR1cm4gZGVjb2RlKHNldHRsZWQpO1xufVxuXG4vKiogQSByZXNvbHZlZCBrZXkgcGx1cyB0aGUgY3V0b2ZmIGl0IGlzIHNjb3BlZCB0by4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbmluZ0tleSB7XG4gIGtleTogVWludDhBcnJheTtcbiAgLyoqIEZvcmNlLWNsZWFyIGN1dG9mZiBpbiBtczsgYDBgIHdoZW4gdW5zZXQuIFRva2VucyBvbGRlciB0aGFuIHRoaXMgYXJlIHJlZnVzZWQuICovXG4gIGN1dG9mZk1zOiBudW1iZXI7XG59XG5cbmxldCBwZW5kaW5nOiBQcm9taXNlPFNpZ25pbmdLZXk+IHwgdW5kZWZpbmVkO1xuXG4vKipcbiAqIFRoZSBzaWduaW5nIGtleSBmb3IgdGhpcyBnYXRlLCByZXNvbHZlZCBvbmNlIHBlciBwcm9jZXNzLlxuICpcbiAqIFJlc29sdmVkIE9OQ0UsIHNvIGBjb25maWd1cmVkQ3V0b2ZmYCBpcyBob25vdXJlZCBvbmx5IG9uIHRoZSBmaXJzdCBjYWxsIC0gdGhlXG4gKiBwbHVnaW4ncyBgc2V0dXAoKWAgcGFzc2VzIGl0cyByZXNvbHZlZCB2YWx1ZSB0aGVyZSwgYmVmb3JlIGFueSByZXF1ZXN0IGNhblxuICogcmVhY2ggdGhlIGxhenkgcGF0aC5cbiAqXG4gKiBgVFVOTkVMX0FVVEhfSldUX1NFQ1JFVGAgd2hlbiBzZXQsIGVsc2UgdGhlIGNhY2hlLWJhY2tlZCBrZXkuIEEgY2FjaGUgdGhhdCBpc1xuICogdW5hdmFpbGFibGUgZGVncmFkZXMgdG8gYW4gZXBoZW1lcmFsIHBlci1wcm9jZXNzIGtleSAodGhlIHByZXZpb3VzIGJlaGF2aW91cilcbiAqIHJhdGhlciB0aGFuIHJlZnVzaW5nIHRvIHNpZ246IHRoZSBrZXkgb25seSB2YWxpZGF0ZXMgYW4gQUxSRUFEWS1pc3N1ZWQgc2Vzc2lvbixcbiAqIHNvIGxvc2luZyBpdCBjb3N0cyBzZXNzaW9ucywgbmV2ZXIgYWRtaXNzaW9uIC0gYSBjYWxsZXIgc3RpbGwgbmVlZHMgYSBjb2RlXG4gKiBkZWxpdmVyZWQgdG8gYW4gYWxsb3ctbGlzdGVkIGFkZHJlc3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduaW5nS2V5KGNvbmZpZ3VyZWRDdXRvZmY/OiBzdHJpbmcgfCBudW1iZXIgfCBEYXRlKTogUHJvbWlzZTxTaWduaW5nS2V5PiB7XG4gIHBlbmRpbmcgPz89IChhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgY3V0b2ZmTXMgPSByZXNvbHZlU2Vzc2lvbkN1dG9mZihjb25maWd1cmVkQ3V0b2ZmKTtcbiAgICBjb25zdCBjb25maWd1cmVkID0gZW52LnRleHQoSldUX1NFQ1JFVF9FTlYpO1xuICAgIGlmIChjb25maWd1cmVkKSB7XG4gICAgICByZXR1cm4geyBrZXk6IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShjb25maWd1cmVkKSwgY3V0b2ZmTXMgfTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB7IGtleTogYXdhaXQgbG9hZEZyb21DYWNoZShjdXRvZmZNcyksIGN1dG9mZk1zIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICBgbm8gJHtlbnYubmFtZShKV1RfU0VDUkVUX0VOVil9IGFuZCB0aGUgY2FjaGUgaXMgdW5hdmFpbGFibGUgLSB1c2luZyBhbiBlcGhlbWVyYWwgcGVyLXByb2Nlc3Mga2V5OyBzZXNzaW9ucyB3aWxsIG5vdCBzdXJ2aXZlIGEgcmVzdGFydGAsXG4gICAgICAgIHsgZXJyb3IgfSxcbiAgICAgICk7XG4gICAgICByZXR1cm4geyBrZXk6IG5ldyBVaW50OEFycmF5KHJhbmRvbUJ5dGVzKEtFWV9CWVRFUykpLCBjdXRvZmZNcyB9O1xuICAgIH1cbiAgfSkoKTtcbiAgcmV0dXJuIHBlbmRpbmc7XG59XG5cbi8qKiBSZXNldCB0aGUgcGVyLXByb2Nlc3Mga2V5ICh0ZXN0cywgb3IgYWZ0ZXIgY2hhbmdpbmcgdGhlIGVudiBpbi1wcm9jZXNzKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNldFNpZ25pbmdLZXkoKTogdm9pZCB7XG4gIHBlbmRpbmcgPSB1bmRlZmluZWQ7XG59XG4iXX0=
173
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmluZy1rZXkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2lnbmluZy1rZXkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBDRztBQUVILE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDMUMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFN0MsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0FBRWhEOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFFakQsa0ZBQWtGO0FBQ2xGLE1BQU0sVUFBVSxHQUFHLDBCQUEwQixDQUFDO0FBRTlDLGtGQUFrRjtBQUNsRixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUM7QUFVckI7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQUMsVUFBbUM7SUFDdEUsTUFBTSxHQUFHLEdBQ1AsVUFBVSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxxQkFBcUIsRUFBRSxvQkFBb0IsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQzFGLElBQUksR0FBRyxLQUFLLFNBQVMsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxFQUFFO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFFOUQsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FB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Q0FBQztBQUU3Qzs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUFDLGdCQUF5QztJQUNsRSxPQUFPLEtBQUssQ0FBQyxLQUFLLElBQUksRUFBRTtRQUN0QixNQUFNLFFBQVEsR0FBRyxvQkFBb0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDakUsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUM7UUFDakUsQ0FBQztRQUNELElBQUksQ0FBQztZQUNILE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxhQUFhLENBQUMsUUFBUSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUM7UUFDMUQsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLENBQUMsSUFBSSxDQUNULE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxhQUFhLENBQUMseUdBQXlHLEVBQzVKLEVBQUUsS0FBSyxFQUFFLENBQ1YsQ0FBQztZQUNGLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxVQUFVLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUM7UUFDbkUsQ0FBQztJQUNILENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDTCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBRUQsK0VBQStFO0FBQy9FLE1BQU0sVUFBVSxlQUFlO0lBQzdCLE9BQU8sR0FBRyxTQUFTLENBQUM7QUFDdEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIGdhdGUncyBIUzI1NiBzZXNzaW9uLXNpZ25pbmcga2V5LCBwZXJzaXN0ZWQgaW4gQXBwS2l0J3MgY2FjaGUuXG4gKlxuICogVGhlIGtleSBkZWNpZGVzIHdoZXRoZXIgYSBzZXNzaW9uIENPT0tJRSBzdGlsbCB2ZXJpZmllcywgc28gaXQgbXVzdCBPVVRMSVZFIHRoZVxuICogcHJvY2VzczogYSBwZXItcHJvY2VzcyBgcmFuZG9tQnl0ZXMoMzIpYCB3b3VsZCBpbnZhbGlkYXRlIGV2ZXJ5IG91dHN0YW5kaW5nIGNvb2tpZVxuICogb24gcmVzdGFydCBhbmQgbWFrZSBlYWNoIHNpZ25lZC1pbiB1c2VyIHJlcXVlc3QgYSBuZXcgY29kZSAtIHBhaW5mdWwgZm9yIGEgdHVubmVsLFxuICogd2hpY2ggcmVzdGFydHMgd2hlbmV2ZXIgdGhlIGFwcCBpdCB3cmFwcyBkb2VzLiBTbyB0aGUga2V5IGlzIHN0b3JlZCBpbiB0aGUgY2FjaGVcbiAqIEFwcEtpdCBhbHJlYWR5IGNvbmZpZ3VyZWQgKG1lbW9yeSwgb3IgTGFrZWJhc2Ugd2hlbiB0aGUgaG9zdCB3aXJlcyBhIHBlcnNpc3RlbnRcbiAqIGBDYWNoZVN0b3JhZ2VgKSwgYW5kIHdpdGggcGVyc2lzdGVudCBzdG9yYWdlIGEgcmVzdGFydCBrZWVwcyBzZXNzaW9ucyBhbGl2ZSBmb3JcbiAqIHtAbGluayBLRVlfVFRMX1NFQ09ORFN9LlxuICpcbiAqIEFuIGV4cGxpY2l0bHkgY29uZmlndXJlZCBgVFVOTkVMX0FVVEhfSldUX1NFQ1JFVGAgc3RpbGwgd2lucyBvdXRyaWdodC4gVGhhdCBpc1xuICogdGhlIHJpZ2h0IGFuc3dlciBmb3IgYSBmbGVldDogYW4gb3BlcmF0b3ItaGVsZCBzZWNyZXQgbmVlZHMgbm8gc2hhcmVkIGNhY2hlIGFuZFxuICogbm8gY29udmVyZ2VuY2UsIGFuZCBpdCBzdXJ2aXZlcyBhIGNhY2hlIGZsdXNoLlxuICpcbiAqICMjIGdldCAvIGdlbmVyYXRlIC8gZ2V0XG4gKlxuICogVHdvIGluc3RhbmNlcyBib290aW5nIGF0IG9uY2UgYm90aCBtaXNzLCBzbyBib3RoIHdvdWxkIGdlbmVyYXRlIC0gYW5kIHRoZSBsb3NlclxuICogd291bGQgc2lnbiBjb29raWVzIHdpdGggYSBrZXkgdGhlIHdpbm5lciByZWplY3RzLiBSZXNvbHV0aW9uIGlzIGEgcmUtUkVBRCBhZnRlclxuICogdGhlIHdyaXRlOiB3aGF0ZXZlciB0aGUgY2FjaGUgaG9sZHMgYWZ0ZXJ3YXJkcyBpcyB0aGUga2V5IGV2ZXJ5b25lIGFkb3B0cywgc29cbiAqIHRoZSBpbnN0YW5jZXMgY29udmVyZ2Ugb24gT05FIHZhbHVlIGluc3RlYWQgb2YgdHJ1c3RpbmcgdGhlIG9uZSB0aGV5IG1pbnRlZC5cbiAqIChgc2V0YCBpcyBub3QgY29uZGl0aW9uYWwgaW4gdGhlIGNhY2hlIEFQSSAtIHRoZXJlIGlzIG5vIGBzZXRueGAgdG8gbGVhbiBvbiAtXG4gKiBhbmQgdGhpcyBydW5zIG9uY2UgcGVyIHByb2Nlc3MsIHNvIHRoZSBleHRyYSByb3VuZC10cmlwIGlzIGZyZWUuKVxuICpcbiAqIEEgcGF0aG9sb2dpY2FsIGludGVybGVhdmUgY2FuIHN0aWxsIGNvc3QgYSBrZXk6IGlmIEEgd3JpdGVzIGJldHdlZW4gQidzIHdyaXRlXG4gKiBhbmQgQidzIHJlLXJlYWQsIEIgYWRvcHRzIEEncyBrZXkgd2hpbGUgQSBhZG9wdHMgaXRzIG93bi4gVGhlIGNvc3QgaXMgYm91bmRlZCAtXG4gKiBhIGNvb2tpZSBtaW50ZWQgaW4gdGhhdCB3aW5kb3cgZmFpbHMgdG8gdmVyaWZ5IGFuZCB0aGUgaG9sZGVyIHNpZ25zIGluIGFnYWluIC1cbiAqIGFuZCBpdCBjYW5ub3QgcHJvZHVjZSBhIGtleSBvbmUgaW5zdGFuY2UgVFJVU1RTIGJ1dCBhbm90aGVyIHJlamVjdHMgZm9yIGxvbmdlclxuICogdGhhbiB0aGUgd2luZG93IGl0c2VsZi4gU2V0IGBUVU5ORUxfQVVUSF9KV1RfU0VDUkVUYCB0byByZW1vdmUgdGhlIHJhY2VcbiAqIGVudGlyZWx5LlxuICpcbiAqICMjIEZvcmNpbmcgZXZlcnkgc2Vzc2lvbiB0byBlbmRcbiAqXG4gKiB7QGxpbmsgcmVzb2x2ZVNlc3Npb25DdXRvZmZ9IHJlYWRzIGEgZGF0ZSBmcm9tIGBUVU5ORUxfQVVUSF9TRVNTSU9OX0NVVE9GRmAgKG9yXG4gKiBgLS1zZXNzaW9uLWN1dG9mZmApLCBhbmQgdGhhdCBkYXRlIGlzIHBhcnQgb2YgdGhlIGNhY2hlIEtFWS4gTW92aW5nIGl0IGZvcndhcmRcbiAqIG1ha2VzIGV2ZXJ5IHByaW9yIGtleSB1bnJlYWNoYWJsZSwgc28gZXZlcnkgY29va2llIHNpZ25lZCBhZ2FpbnN0IGl0IHN0b3BzXG4gKiB2ZXJpZnlpbmcgLSB0aGUgbG9nLWV2ZXJ5b25lLW91dCBzd2l0Y2gsIHdpdGhvdXQgaGF2aW5nIHRvIGZpbmQgYW5kIGZsdXNoIGFcbiAqIGNhY2hlIGVudHJ5LiBUaGUgY3V0b2ZmIGlzIGFsc28gYXNzZXJ0ZWQgYWdhaW5zdCBlYWNoIHRva2VuJ3MgYGlhdGAsIHNvIGFcbiAqIGNvb2tpZSB0aGF0IHByZWRhdGVzIGl0IGlzIHJlZnVzZWQgZXZlbiBpZiBpdCB3YXMgc2lnbmVkIHdpdGggdGhlIGtleSB0aGF0IGlzXG4gKiBzb21laG93IHN0aWxsIGN1cnJlbnQuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5pbXBvcnQgeyBDYWNoZU1hbmFnZXIgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBjb25maWcgfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgeyBsb2csIG9iamVjdCB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBUVU5ORUxfQ09ORklHIH0gZnJvbSBcIi4vX2NvbmZpZy50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsOnNpZ25pbmcta2V5XCIpO1xuXG4vKipcbiAqIEhvdyBsb25nIGEgY2FjaGVkIHNpZ25pbmcga2V5IGxpdmVzOiAzMCBkYXlzLlxuICpcbiAqIFRoaXMgaXMgdGhlIGNlaWxpbmcgb24gaG93IGxvbmcgYSBzZXNzaW9uIGNvb2tpZSBjYW4gc3RheSB2YWxpZCBhY3Jvc3NcbiAqIHJlc3RhcnRzLCBzbyBpdCBpcyBkZWxpYmVyYXRlbHkgPj0gdGhlIGRlZmF1bHQgc2Vzc2lvbiBUVEwgLSBhIGtleSB0aGF0IGV4cGlyZWRcbiAqIGJlZm9yZSB0aGUgY29va2llcyBpdCBzaWduZWQgd291bGQgbG9nIGV2ZXJ5b25lIG91dCBmb3Igbm8gcmVhc29uLlxuICovXG5leHBvcnQgY29uc3QgS0VZX1RUTF9TRUNPTkRTID0gMzAgKiAyNCAqIDYwICogNjA7XG5cbi8qKiBDYWNoZS1rZXkgcHJlZml4IGZvciB0aGUgc2lnbmluZyBrZXksIG5hbWVzcGFjZWQgYXdheSBmcm9tIG90aGVyIGNhY2hlIHVzZS4gKi9cbmNvbnN0IEtFWV9QUkVGSVggPSBcInR1bm5lbDphdXRoOnNpZ25pbmcta2V5OlwiO1xuXG4vKiogQnl0ZXMgb2YgZW50cm9weSBpbiBhIGdlbmVyYXRlZCBrZXkgKDI1Ni1iaXQsIG1hdGNoaW5nIEhTMjU2J3MgaGFzaCB3aWR0aCkuICovXG5jb25zdCBLRVlfQllURVMgPSAzMjtcblxuLyoqIFdoYXQgdGhlIGNhY2hlIHN0b3JlczogdGhlIGtleSBwbHVzIHdoZW4gaXQgd2FzIG1pbnRlZCwgZm9yIG9ic2VydmFiaWxpdHkuICovXG5pbnRlcmZhY2UgU3RvcmVkS2V5IHtcbiAgLyoqIEJhc2U2NHVybCBvZiB0aGUgcmF3IGtleSBieXRlcy4gKi9cbiAgc2VjcmV0OiBzdHJpbmc7XG4gIC8qKiBXaGVuIHRoaXMga2V5IHdhcyBnZW5lcmF0ZWQsIElTTy04NjAxLiAqL1xuICBjcmVhdGVkQXQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBmb3JjZS1jbGVhciBjdXRvZmYgYXMgZXBvY2ggTUlMTElTRUNPTkRTLCBvciBgMGAgd2hlbiB1bnNldC5cbiAqXG4gKiBBY2NlcHRzIHdoYXRldmVyIGBvYmplY3QudG9EYXRlYCBhY2NlcHRzIC0gYSBgRGF0ZWAsIGAyMDI2LTA4LTAyYCwgYW4gSVNPXG4gKiBpbnN0YW50LCBlcG9jaCBzZWNvbmRzIG9yIG1pbGxpcyBmcm9tIGBkYXRlICslc2AsIG9yIGEgcmVsYXRpdmUgZHVyYXRpb25cbiAqIChgLTMwZGAsIGA3IGRheXMgYWdvYCksIHdoaWNoIGlzIHRoZSBzcGVsbGluZyBhbiBvcGVyYXRvciByZWFjaGluZyBmb3IgdGhpc1xuICogdXN1YWxseSB3YW50czogc2lnbiBvdXQgZXZlcnlvbmUgd2hvIHNpZ25lZCBpbiBtb3JlIHRoYW4gYSBtb250aCBhZ28uXG4gKlxuICogQW4gVU5QQVJTRUFCTEUgdmFsdWUgaXMgaWdub3JlZCB3aXRoIGEgd2FybmluZyByYXRoZXIgdGhhbiB0aHJvd2luZzogdGhpcyBpc1xuICogdGhlIHN3aXRjaCB0aGF0IGxvZ3MgYSBmbGVldCBiYWNrIGluLCBhbmQgZmFpbGluZyB0byBib290IG92ZXIgYSB0eXBvIGlzIHdvcnNlXG4gKiB0aGFuIG5vdCByb3RhdGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTZXNzaW9uQ3V0b2ZmKGNvbmZpZ3VyZWQ/OiBzdHJpbmcgfCBudW1iZXIgfCBEYXRlKTogbnVtYmVyIHtcbiAgY29uc3QgcmF3ID1cbiAgICBjb25maWd1cmVkID8/IGNvbmZpZy50ZXh0KFtcIkFVVEhfU0VTU0lPTl9DVVRPRkZcIiwgXCJBVVRIX1NFU1NJT05fRVBPQ0hcIl0sIFRVTk5FTF9DT05GSUcpO1xuICBpZiAocmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSBudWxsIHx8IHJhdyA9PT0gXCJcIikgcmV0dXJuIDA7XG5cbiAgY29uc3QgZGF0ZSA9IG9iamVjdC50b0RhdGUocmF3KTtcbiAgaWYgKCFkYXRlKSB7XG4gICAgbG9nZ2VyLndhcm4oYGlnbm9yaW5nIHVucGFyc2VhYmxlICR7Y29uZmlnLm5hbWUoXCJBVVRIX1NFU1NJT05fQ1VUT0ZGXCIsIFRVTk5FTF9DT05GSUcpfWAsIHtcbiAgICAgIHZhbHVlOiBTdHJpbmcocmF3KSxcbiAgICB9KTtcbiAgICByZXR1cm4gMDtcbiAgfVxuICByZXR1cm4gY2xhbXBUb1Bhc3QoZGF0ZS5nZXRUaW1lKCkpO1xufVxuXG4vKipcbiAqIEhvbGQgdGhlIGN1dG9mZiBhdCBcIm5vd1wiLCBiZWNhdXNlIGEgRlVUVVJFIGN1dG9mZiB3b3VsZCByZWZ1c2UgdGhlIHNlc3Npb25zIGl0XG4gKiBpcyBhYm91dCB0byBtaW50IGFzIHdlbGwgYXMgdGhlIG9sZCBvbmVzIC0gYW4gYXBwIG5vYm9keSBjYW4gc2lnbiBpbiB0bywgZnJvbSBhXG4gKiBtaXN0eXBlZCB5ZWFyLCB3aXRoIHRoZSBmaXggaGlkZGVuIGJlaGluZCB1bmRlcnN0YW5kaW5nIHRoaXMgZmxhZy4gQ2xhbXBlZCwgYVxuICogZnV0dXJlIGRhdGUgbWVhbnMgd2hhdCBhbiBvcGVyYXRvciBzZXR0aW5nIGl0IGFsd2F5cyBtZWFudDogY2xlYXIgZXZlcnl0aGluZ1xuICogb3V0c3RhbmRpbmcsIHRoZW4gY2Fycnkgb24uXG4gKi9cbmZ1bmN0aW9uIGNsYW1wVG9QYXN0KGN1dG9mZk1zOiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICBpZiAoY3V0b2ZmTXMgPD0gbm93KSByZXR1cm4gY3V0b2ZmTXM7XG4gIGxvZ2dlci53YXJuKFxuICAgIGAke2NvbmZpZy5uYW1lKFwiQVVUSF9TRVNTSU9OX0NVVE9GRlwiLCBUVU5ORUxfQ09ORklHKX0gaXMgaW4gdGhlIGZ1dHVyZSAtIGNsYW1waW5nIHRvIG5vd2AsXG4gICAge1xuICAgICAgY29uZmlndXJlZDogbmV3IERhdGUoY3V0b2ZmTXMpLnRvSVNPU3RyaW5nKCksXG4gICAgfSxcbiAgKTtcbiAgcmV0dXJuIG5vdztcbn1cblxuLyoqIFRoZSBjYWNoZSBrZXkgZm9yIG9uZSBjdXRvZmYsIHNvIG1vdmluZyB0aGUgY3V0b2ZmIG9ycGhhbnMgZXZlcnkgZWFybGllciBrZXkuICovXG5mdW5jdGlvbiBjYWNoZUtleShjdXRvZmZNczogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke0tFWV9QUkVGSVh9JHtjdXRvZmZNc31gO1xufVxuXG5mdW5jdGlvbiBkZWNvZGUoc3RvcmVkOiBTdG9yZWRLZXkpOiBVaW50OEFycmF5IHtcbiAgcmV0dXJuIG5ldyBVaW50OEFycmF5KEJ1ZmZlci5mcm9tKHN0b3JlZC5zZWNyZXQsIFwiYmFzZTY0dXJsXCIpKTtcbn1cblxuLyoqXG4gKiBMb2FkIHRoZSBzaWduaW5nIGtleSBmb3IgYGN1dG9mZk1zYCBmcm9tIHRoZSBjYWNoZSwgbWludGluZyBhbmQgc3RvcmluZyBvbmVcbiAqIHdoZW4gYWJzZW50LiBTZWUgdGhlIG1vZHVsZSBkb2NzIGZvciB3aHkgdGhlIHdyaXRlIGlzIGZvbGxvd2VkIGJ5IGEgcmUtcmVhZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbG9hZEZyb21DYWNoZShjdXRvZmZNczogbnVtYmVyKTogUHJvbWlzZTxVaW50OEFycmF5PiB7XG4gIGNvbnN0IGNhY2hlID0gQ2FjaGVNYW5hZ2VyLmdldEluc3RhbmNlU3luYygpO1xuICBjb25zdCBrZXkgPSBjYWNoZUtleShjdXRvZmZNcyk7XG5cbiAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBjYWNoZS5nZXQ8U3RvcmVkS2V5PihrZXkpO1xuICBpZiAoZXhpc3Rpbmc/LnNlY3JldCkge1xuICAgIGxvZ2dlci5pbmZvKFwicmV1c2luZyBjYWNoZWQgc2lnbmluZyBrZXlcIiwgeyBjcmVhdGVkQXQ6IGV4aXN0aW5nLmNyZWF0ZWRBdCB9KTtcbiAgICByZXR1cm4gZGVjb2RlKGV4aXN0aW5nKTtcbiAgfVxuXG4gIGNvbnN0IG1pbnRlZDogU3RvcmVkS2V5ID0ge1xuICAgIHNlY3JldDogQnVmZmVyLmZyb20ocmFuZG9tQnl0ZXMoS0VZX0JZVEVTKSkudG9TdHJpbmcoXCJiYXNlNjR1cmxcIiksXG4gICAgY3JlYXRlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gIH07XG4gIGF3YWl0IGNhY2hlLnNldChrZXksIG1pbnRlZCwgeyB0dGw6IEtFWV9UVExfU0VDT05EUyB9KTtcblxuICAvLyBSZS1yZWFkIHJhdGhlciB0aGFuIHRydXN0aW5nIGBtaW50ZWRgOiBhbm90aGVyIGluc3RhbmNlIHRoYXQgcmFjZWQgdGhpcyBib290XG4gIC8vIG1heSBoYXZlIHdyaXR0ZW4gZmlyc3QsIGFuZCBhZG9wdGluZyB3aGF0ZXZlciBpcyBzdG9yZWQgaXMgd2hhdCBtYWtlcyB0aGUgdHdvXG4gIC8vIGNvbnZlcmdlIG9uIG9uZSBrZXkuXG4gIGNvbnN0IHNldHRsZWQgPSAoYXdhaXQgY2FjaGUuZ2V0PFN0b3JlZEtleT4oa2V5KSkgPz8gbWludGVkO1xuICBsb2dnZXIuaW5mbyhcInN0b3JlZCBhIG5ldyBzaWduaW5nIGtleVwiLCB7XG4gICAgY3JlYXRlZEF0OiBzZXR0bGVkLmNyZWF0ZWRBdCxcbiAgICB0dGxTZWNvbmRzOiBLRVlfVFRMX1NFQ09ORFMsXG4gICAgYWRvcHRlZDogc2V0dGxlZC5jcmVhdGVkQXQgPT09IG1pbnRlZC5jcmVhdGVkQXQgPyBcIm93blwiIDogXCJjb25jdXJyZW50LWluc3RhbmNlXCIsXG4gIH0pO1xuICByZXR1cm4gZGVjb2RlKHNldHRsZWQpO1xufVxuXG4vKiogQSByZXNvbHZlZCBrZXkgcGx1cyB0aGUgY3V0b2ZmIGl0IGlzIHNjb3BlZCB0by4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbmluZ0tleSB7XG4gIGtleTogVWludDhBcnJheTtcbiAgLyoqIEZvcmNlLWNsZWFyIGN1dG9mZiBpbiBtczsgYDBgIHdoZW4gdW5zZXQuIFRva2VucyBvbGRlciB0aGFuIHRoaXMgYXJlIHJlZnVzZWQuICovXG4gIGN1dG9mZk1zOiBudW1iZXI7XG59XG5cbmxldCBwZW5kaW5nOiBQcm9taXNlPFNpZ25pbmdLZXk+IHwgdW5kZWZpbmVkO1xuXG4vKipcbiAqIFRoZSBzaWduaW5nIGtleSBmb3IgdGhpcyBnYXRlLCByZXNvbHZlZCBvbmNlIHBlciBwcm9jZXNzLlxuICpcbiAqIFJlc29sdmVkIE9OQ0UsIHNvIGBjb25maWd1cmVkQ3V0b2ZmYCBpcyBob25vdXJlZCBvbmx5IG9uIHRoZSBmaXJzdCBjYWxsIC0gdGhlXG4gKiBwbHVnaW4ncyBgc2V0dXAoKWAgcGFzc2VzIGl0cyByZXNvbHZlZCB2YWx1ZSB0aGVyZSwgYmVmb3JlIGFueSByZXF1ZXN0IGNhblxuICogcmVhY2ggdGhlIGxhenkgcGF0aC5cbiAqXG4gKiBgVFVOTkVMX0FVVEhfSldUX1NFQ1JFVGAgd2hlbiBzZXQsIGVsc2UgdGhlIGNhY2hlLWJhY2tlZCBrZXkuIEEgY2FjaGUgdGhhdCBpc1xuICogdW5hdmFpbGFibGUgZGVncmFkZXMgdG8gYW4gZXBoZW1lcmFsIHBlci1wcm9jZXNzIGtleSAodGhlIHByZXZpb3VzIGJlaGF2aW91cilcbiAqIHJhdGhlciB0aGFuIHJlZnVzaW5nIHRvIHNpZ246IHRoZSBrZXkgb25seSB2YWxpZGF0ZXMgYW4gQUxSRUFEWS1pc3N1ZWQgc2Vzc2lvbixcbiAqIHNvIGxvc2luZyBpdCBjb3N0cyBzZXNzaW9ucywgbmV2ZXIgYWRtaXNzaW9uIC0gYSBjYWxsZXIgc3RpbGwgbmVlZHMgYSBjb2RlXG4gKiBkZWxpdmVyZWQgdG8gYW4gYWxsb3ctbGlzdGVkIGFkZHJlc3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduaW5nS2V5KGNvbmZpZ3VyZWRDdXRvZmY/OiBzdHJpbmcgfCBudW1iZXIgfCBEYXRlKTogUHJvbWlzZTxTaWduaW5nS2V5PiB7XG4gIHBlbmRpbmcgPz89IChhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgY3V0b2ZmTXMgPSByZXNvbHZlU2Vzc2lvbkN1dG9mZihjb25maWd1cmVkQ3V0b2ZmKTtcbiAgICBjb25zdCBjb25maWd1cmVkID0gY29uZmlnLnRleHQoXCJBVVRIX0pXVF9TRUNSRVRcIiwgVFVOTkVMX0NPTkZJRyk7XG4gICAgaWYgKGNvbmZpZ3VyZWQpIHtcbiAgICAgIHJldHVybiB7IGtleTogbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKGNvbmZpZ3VyZWQpLCBjdXRvZmZNcyB9O1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHsga2V5OiBhd2FpdCBsb2FkRnJvbUNhY2hlKGN1dG9mZk1zKSwgY3V0b2ZmTXMgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgIGBubyAke2NvbmZpZy5uYW1lKFwiQVVUSF9KV1RfU0VDUkVUXCIsIFRVTk5FTF9DT05GSUcpfSBhbmQgdGhlIGNhY2hlIGlzIHVuYXZhaWxhYmxlIC0gdXNpbmcgYW4gZXBoZW1lcmFsIHBlci1wcm9jZXNzIGtleTsgc2Vzc2lvbnMgd2lsbCBub3Qgc3Vydml2ZSBhIHJlc3RhcnRgLFxuICAgICAgICB7IGVycm9yIH0sXG4gICAgICApO1xuICAgICAgcmV0dXJuIHsga2V5OiBuZXcgVWludDhBcnJheShyYW5kb21CeXRlcyhLRVlfQllURVMpKSwgY3V0b2ZmTXMgfTtcbiAgICB9XG4gIH0pKCk7XG4gIHJldHVybiBwZW5kaW5nO1xufVxuXG4vKiogUmVzZXQgdGhlIHBlci1wcm9jZXNzIGtleSAodGVzdHMsIG9yIGFmdGVyIGNoYW5naW5nIHRoZSBlbnYgaW4tcHJvY2VzcykuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzZXRTaWduaW5nS2V5KCk6IHZvaWQge1xuICBwZW5kaW5nID0gdW5kZWZpbmVkO1xufVxuIl19
@@ -1 +1 @@
1
- {"root":["../src/allowlist.ts","../src/code-email.ts","../src/env.ts","../src/gate.ts","../src/headers.ts","../src/interceptor.ts","../src/otp.ts","../src/plugin.ts","../src/portr.ts","../src/rate-limit.ts","../src/send-code.ts","../src/signing-key.ts","../index.ts"],"version":"5.9.3"}
1
+ {"root":["../src/_config.ts","../src/allowlist.ts","../src/code-email.ts","../src/gate.ts","../src/headers.ts","../src/interceptor.ts","../src/otp.ts","../src/plugin.ts","../src/portr.ts","../src/rate-limit.ts","../src/send-code.ts","../src/signing-key.ts","../index.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -18,20 +18,20 @@
18
18
  "projen": "projen"
19
19
  },
20
20
  "devDependencies": {
21
- "@dbx-tools/email": "0.6.82",
21
+ "@dbx-tools/email": "0.6.86",
22
22
  "@types/bun": "^1.3.14",
23
23
  "@types/node": "^24.6.0",
24
24
  "typescript": "^5.9.3"
25
25
  },
26
26
  "peerDependencies": {
27
- "@dbx-tools/email": "0.6.82"
27
+ "@dbx-tools/email": "0.6.86"
28
28
  },
29
29
  "dependencies": {
30
30
  "@databricks/appkit": "^0.43.0",
31
- "@dbx-tools/appkit": "0.6.82",
32
- "@dbx-tools/core": "0.6.82",
33
- "@dbx-tools/shared-core": "0.6.82",
34
- "@dbx-tools/shared-email": "0.6.82",
31
+ "@dbx-tools/appkit": "0.6.86",
32
+ "@dbx-tools/core": "0.6.86",
33
+ "@dbx-tools/shared-core": "0.6.86",
34
+ "@dbx-tools/shared-email": "0.6.86",
35
35
  "jose": "^6.2.3"
36
36
  },
37
37
  "main": "./lib/index.js",
@@ -48,7 +48,7 @@
48
48
  "./package.json": "./package.json"
49
49
  }
50
50
  },
51
- "version": "0.6.82",
51
+ "version": "0.6.86",
52
52
  "types": "./lib/index.d.ts",
53
53
  "type": "module",
54
54
  "exports": {
package/src/_config.ts ADDED
@@ -0,0 +1,2 @@
1
+ /** Package-private namespace options for layered tunnel configuration. */
2
+ export const TUNNEL_CONFIG = { prefix: "TUNNEL" } as const;
package/src/gate.ts CHANGED
@@ -22,10 +22,11 @@
22
22
  * @module
23
23
  */
24
24
 
25
+ import type { IncomingMessage } from "node:http";
25
26
  import { http, json, log, token } from "@dbx-tools/shared-core";
26
27
  import { authRequestSchema, authVerifySchema, SESSION_COOKIE_NAME } from "@dbx-tools/shared-email";
27
28
  import type { Request, RequestHandler, Response } from "express";
28
- import { toHeaderPolicy } from "./headers.ts";
29
+ import { toHeaderPolicy, type HeaderPolicy } from "./headers.ts";
29
30
  import type { AuthGateApi } from "./plugin.ts";
30
31
 
31
32
  const logger = log.logger("tunnel:gate");
@@ -56,7 +57,7 @@ export interface GateOptions {
56
57
  * over portr. Case-insensitive; the optional `:port` is ignored. When no public
57
58
  * domain is configured, nothing is tunnel traffic.
58
59
  */
59
- export function isTunnelHost(req: Request, publicDomain: string | undefined): boolean {
60
+ export function isTunnelHost(req: IncomingMessage, publicDomain: string | undefined): boolean {
60
61
  if (!publicDomain) return false;
61
62
  const host = (req.headers.host ?? "").toLowerCase().split(":")[0];
62
63
  return host === publicDomain.toLowerCase().split(":")[0];
@@ -84,7 +85,7 @@ function sessionCookie(value: string, maxAgeSeconds: number): string {
84
85
  * rightmost, not the leftmost, stops a caller minting a fresh rate-limit bucket by
85
86
  * varying the header. Called before {@link stripHeaders}.
86
87
  */
87
- function clientIp(req: Request): string {
88
+ export function clientIp(req: IncomingMessage): string {
88
89
  const forwarded = req.headers["x-forwarded-for"];
89
90
  const chain = (Array.isArray(forwarded) ? forwarded.join(",") : (forwarded ?? ""))
90
91
  .split(",")
@@ -98,7 +99,7 @@ function clientIp(req: Request): string {
98
99
  * handlers run, so the app never sees `dbx_auth` (it is the gate's concern).
99
100
  * Preserves other cookies; deletes the header when it becomes empty.
100
101
  */
101
- function stripSessionCookie(req: Request): void {
102
+ function stripSessionCookie(req: IncomingMessage): void {
102
103
  const raw = req.headers.cookie;
103
104
  if (!raw) return;
104
105
  const kept = raw
@@ -120,7 +121,7 @@ function stripSessionCookie(req: Request): void {
120
121
  * `@dbx-tools/appkit`'s `identity: "auto"` detects, so a gated request runs as the
121
122
  * app service principal instead of throwing.
122
123
  */
123
- function injectIdentity(req: Request, email: string): void {
124
+ function injectIdentity(req: IncomingMessage, email: string): void {
124
125
  req.headers[token.USER_ID_HEADER] = email;
125
126
  req.headers[token.USER_EMAIL_HEADER] = email;
126
127
  }
@@ -145,6 +146,80 @@ function readBody(req: Request): Promise<string> {
145
146
  });
146
147
  }
147
148
 
149
+ /**
150
+ * What the caller should do with a request, from {@link gateRequest}.
151
+ *
152
+ * - `pass` - not tunnel traffic, or an open login route. Forward untouched.
153
+ * - `allow` - tunnel traffic that is authorized. The request's headers have
154
+ * ALREADY been rewritten (policy applied, identity injected, session cookie
155
+ * stripped), so forward it as it now stands.
156
+ * - `deny` - tunnel traffic with no valid session. Answer `401` with
157
+ * {@link AUTH_PREFIX} as the login path.
158
+ */
159
+ export type GateAction = "pass" | "allow" | "deny";
160
+
161
+ /**
162
+ * THE gating decision, for one request, independent of how it will be answered.
163
+ *
164
+ * Both paths call this: the Express middleware below (where the app is the
165
+ * process) and `@dbx-tools/cli-tunnel`'s reverse proxy (where the app is a child
166
+ * process on a private port). A divergence between them would be a security bug
167
+ * the second path could not be tested into agreement - one path forgetting to
168
+ * strip `x-forwarded-access-token` is enough - so the decision, the header
169
+ * rewriting, and the identity injection live here once and the transports only
170
+ * differ in how they WRITE the outcome.
171
+ *
172
+ * Mutates `req.headers` on the `allow`/`pass`-with-cookie paths, which is exactly
173
+ * what both callers want: Express hands the same object to the app's handlers, and
174
+ * the proxy forwards it upstream.
175
+ */
176
+ export async function gateRequest(
177
+ req: IncomingMessage,
178
+ options: GateOptions & { headerPolicy?: HeaderPolicy },
179
+ ): Promise<GateAction> {
180
+ const { gate, publicDomain } = options;
181
+ // Not tunnel traffic (platform front door, or any other local caller): the
182
+ // request is already authenticated, or is not ours to gate.
183
+ if (!isTunnelHost(req, publicDomain)) return "pass";
184
+
185
+ const path = (req.url ?? "/").split("?")[0] ?? "/";
186
+ // The login flow is open so the browser can render <AuthGate> and sign in.
187
+ if (path.startsWith(AUTH_PREFIX)) return "pass";
188
+
189
+ // Anti-spoof: only the gate may assert identity on tunnel traffic.
190
+ const policy = options.headerPolicy ?? toHeaderPolicy(options.forwardHeaders);
191
+ const removed = policy.apply(req.headers as Record<string, unknown>);
192
+ if (removed.length) logger.debug("stripped inbound headers", { removed });
193
+
194
+ // Static (non-API) loads freely so the SPA can render; drop the gate cookie.
195
+ if (!path.startsWith("/api/")) {
196
+ stripSessionCookie(req);
197
+ return "pass";
198
+ }
199
+
200
+ // Every other /api/* needs a valid OTP session.
201
+ const cookie = http.parseCookies(req.headers.cookie ?? null)[SESSION_COOKIE_NAME];
202
+ const email = await gate.session(cookie);
203
+ if (!email) return "deny";
204
+ injectIdentity(req, email);
205
+ stripSessionCookie(req);
206
+ return "allow";
207
+ }
208
+
209
+ /** The body of a `deny`, shared so both paths answer a 401 identically. */
210
+ export const UNAUTHORIZED_BODY = {
211
+ error: "authentication required",
212
+ loginPath: AUTH_PREFIX,
213
+ } as const;
214
+
215
+ /** The `Set-Cookie` value that issues a verified session. */
216
+ export function sessionSetCookie(sessionToken: string, maxAgeSeconds: number): string {
217
+ return sessionCookie(sessionToken, maxAgeSeconds);
218
+ }
219
+
220
+ /** The `Set-Cookie` value that clears the session. */
221
+ export const LOGOUT_SET_COOKIE = `${SESSION_COOKIE_NAME}=; Path=/; HttpOnly; Max-Age=0`;
222
+
148
223
  /**
149
224
  * Register the login routes and the gating middleware on the app's Express
150
225
  * instance. Called from {@link AuthGatePlugin} with the router AppKit hands
@@ -163,11 +238,6 @@ export function mountGate(
163
238
  const headerPolicy = toHeaderPolicy(forwardHeaders);
164
239
  logger.debug("gate mounted", { publicDomain, forward: headerPolicy.patterns });
165
240
 
166
- const applyHeaderPolicy = (req: Request): void => {
167
- const removed = headerPolicy.apply(req.headers as Record<string, unknown>);
168
- if (removed.length) logger.debug("stripped inbound headers", { removed });
169
- };
170
-
171
241
  // --- Login routes (open on tunnel traffic; answered in-process) ---
172
242
 
173
243
  const statusHandler = (async (req, res) => {
@@ -216,7 +286,7 @@ export function mountGate(
216
286
  sendJson(res, 404, { error: "not found" });
217
287
  return;
218
288
  }
219
- sendJson(res, 200, { ok: true }, `${SESSION_COOKIE_NAME}=; Path=/; HttpOnly; Max-Age=0`);
289
+ sendJson(res, 200, { ok: true }, LOGOUT_SET_COOKIE);
220
290
  }) as RequestHandler;
221
291
 
222
292
  addRoute("get", `${AUTH_PREFIX}/status`, statusHandler);
@@ -227,34 +297,9 @@ export function mountGate(
227
297
  // --- The gate middleware (runs before static + the app's /api handlers) ---
228
298
 
229
299
  const gateMiddleware = (async (req, res, next) => {
230
- // Not tunnel traffic (platform front door, or any other local caller): the
231
- // request is already authenticated (or is not ours to gate). Pass through.
232
- if (!isTunnelHost(req, publicDomain)) return next();
233
-
234
- const path = (req.url ?? "/").split("?")[0] ?? "/";
235
-
236
- // The login flow is open so the browser can render <AuthGate> and sign in.
237
- if (path.startsWith(AUTH_PREFIX)) return next();
238
-
239
- // Anti-spoof: only the gate may assert identity on tunnel traffic.
240
- applyHeaderPolicy(req);
241
-
242
- // Static (non-API) loads freely so the SPA can render; drop the gate cookie.
243
- if (!path.startsWith("/api/")) {
244
- stripSessionCookie(req);
245
- return next();
246
- }
247
-
248
- // Every other /api/* needs a valid OTP session.
249
- const cookie = http.parseCookies(req.headers.cookie ?? null)[SESSION_COOKIE_NAME];
250
- const email = await gate.session(cookie);
251
- if (!email) {
252
- sendJson(res, 401, { error: "authentication required", loginPath: AUTH_PREFIX });
253
- return;
254
- }
255
- injectIdentity(req, email);
256
- stripSessionCookie(req);
257
- next();
300
+ const action = await gateRequest(req, { gate, publicDomain, headerPolicy });
301
+ if (action === "deny") sendJson(res, 401, UNAUTHORIZED_BODY);
302
+ else next();
258
303
  }) as RequestHandler;
259
304
 
260
305
  addMiddleware("/", gateMiddleware);
package/src/plugin.ts CHANGED
@@ -17,21 +17,12 @@
17
17
  */
18
18
 
19
19
  import { Plugin, toPlugin, type BasePluginConfig, type PluginManifest } from "@databricks/appkit";
20
- import { brand, env, log, object, string } from "@dbx-tools/shared-core";
20
+ import { config as configModule } from "@dbx-tools/core";
21
+ import { brand, log, object, string } from "@dbx-tools/shared-core";
21
22
  import type { AuthStatus } from "@dbx-tools/shared-email";
22
23
  import type { RequestHandler } from "express";
24
+ import { TUNNEL_CONFIG } from "./_config.ts";
23
25
  import { looksLikeEmail, matchesAllowlist } from "./allowlist.ts";
24
- import {
25
- ALLOW_ENV,
26
- BRAND_NAME_ENV,
27
- CODE_TTL_ENV,
28
- FORWARD_HEADERS_ENV,
29
- INSECURE_ENV,
30
- MESSAGE_ENV,
31
- PUBLIC_DOMAIN_ENV,
32
- SESSION_TTL_ENV,
33
- SUBJECT_ENV,
34
- } from "./env.ts";
35
26
  import { mountGate, type GateOptions } from "./gate.ts";
36
27
  import { CodeStore, signSession, verifySession } from "./otp.ts";
37
28
  import { RateLimiter } from "./rate-limit.ts";
@@ -216,26 +207,36 @@ export function resolveAuthGateConfig(config: AuthGateConfig): ResolvedAuthGateC
216
207
  return {
217
208
  // Both sources are unioned rather than one overriding: a deployment-wide
218
209
  // TUNNEL_AUTH_ALLOW and a per-invocation `--allow` should both grant access.
219
- // Hence `parseList` on each rather than `env.list`, which stops at the first
220
- // source that yields anything.
221
- allow: [...string.parseList(config.allow), ...string.parseList(env.text(ALLOW_ENV))],
222
- subject: env.string(config.subject, SUBJECT_ENV) ?? DEFAULTS.subject,
223
- brandName: env.string(config.brandName, BRAND_NAME_ENV) ?? DEFAULTS.brandName,
224
- message: env.string(config.message, MESSAGE_ENV) ?? DEFAULTS.message,
225
- sessionTtlSeconds: env.positiveInt(
210
+ // Hence `parseList` on each rather than `config.list`, which stops at the
211
+ // first source that yields anything.
212
+ allow: [
213
+ ...string.parseList(config.allow),
214
+ ...string.parseList(configModule.text(["AUTH_ALLOW", "EMAIL_AUTH_ALLOW"], TUNNEL_CONFIG)),
215
+ ],
216
+ subject: configModule.string(config.subject, "AUTH_SUBJECT", TUNNEL_CONFIG) ?? DEFAULTS.subject,
217
+ brandName:
218
+ configModule.string(config.brandName, "AUTH_BRAND_NAME", TUNNEL_CONFIG) ?? DEFAULTS.brandName,
219
+ message: configModule.string(config.message, "AUTH_MESSAGE", TUNNEL_CONFIG) ?? DEFAULTS.message,
220
+ sessionTtlSeconds: configModule.positiveInt(
226
221
  config.sessionTtlSeconds,
227
- SESSION_TTL_ENV,
222
+ "AUTH_SESSION_TTL",
228
223
  DEFAULTS.sessionTtlSeconds,
224
+ TUNNEL_CONFIG,
225
+ ),
226
+ codeTtlSeconds: configModule.positiveInt(
227
+ config.codeTtlSeconds,
228
+ "AUTH_CODE_TTL",
229
+ DEFAULTS.codeTtlSeconds,
230
+ TUNNEL_CONFIG,
229
231
  ),
230
- codeTtlSeconds: env.positiveInt(config.codeTtlSeconds, CODE_TTL_ENV, DEFAULTS.codeTtlSeconds),
231
232
  maxAttempts: config.maxAttempts ?? DEFAULTS.maxAttempts,
232
233
  sessionCutoffMs: resolveSessionCutoff(config.sessionCutoff),
233
- publicDomain: env.string(config.publicDomain, PUBLIC_DOMAIN_ENV) ?? undefined,
234
+ publicDomain: configModule.string(config.publicDomain, "PUBLIC_DOMAIN", TUNNEL_CONFIG),
234
235
  forwardHeaders: [
235
236
  ...string.parseList(config.forwardHeaders),
236
- ...string.parseList(env.text(FORWARD_HEADERS_ENV)),
237
+ ...string.parseList(configModule.text("FORWARD_HEADERS", TUNNEL_CONFIG)),
237
238
  ],
238
- insecure: env.boolean(config.insecure, INSECURE_ENV) ?? false,
239
+ insecure: configModule.boolean(config.insecure, "INSECURE", TUNNEL_CONFIG) ?? false,
239
240
  };
240
241
  }
241
242
 
package/src/portr.ts CHANGED
@@ -15,9 +15,9 @@ import os from "node:os";
15
15
  import { delimiter, join } from "node:path";
16
16
  import { promisify } from "node:util";
17
17
 
18
- import { bin } from "@dbx-tools/core";
19
- import { env, log } from "@dbx-tools/shared-core";
20
- import { PUBLIC_DOMAIN_ENV } from "./env.ts";
18
+ import { bin, config } from "@dbx-tools/core";
19
+ import { log } from "@dbx-tools/shared-core";
20
+ import { TUNNEL_CONFIG } from "./_config.ts";
21
21
 
22
22
  const logger = log.logger("tunnel:portr");
23
23
  const PORTR_VERSION = "1.0.15-sse.2";
@@ -52,8 +52,8 @@ export function resolvePortrConfig(opts: {
52
52
  port: number;
53
53
  }): PortrConfig | undefined {
54
54
  // PORTR_* is upstream portr's own namespace, so it keeps its name.
55
- const token = env.string(opts.token, "PORTR_TOKEN");
56
- const domain = env.string(opts.publicDomain, PUBLIC_DOMAIN_ENV);
55
+ const token = config.string(opts.token, "PORTR_TOKEN");
56
+ const domain = config.string(opts.publicDomain, "PUBLIC_DOMAIN", TUNNEL_CONFIG);
57
57
  if (!token) return undefined;
58
58
  let subdomain = opts.subdomain;
59
59
  let server: string | undefined;
@@ -61,7 +61,7 @@ export function resolvePortrConfig(opts: {
61
61
  subdomain ??= domain.split(".")[0];
62
62
  server = domain.slice(domain.indexOf(".") + 1);
63
63
  }
64
- server ??= env.text("PORTR_SERVER") ?? undefined;
64
+ server ??= config.text("PORTR_SERVER");
65
65
  if (!subdomain || !server || server === domain) return undefined;
66
66
  return { subdomain, server, token, port: opts.port };
67
67
  }
@@ -44,8 +44,9 @@
44
44
 
45
45
  import { randomBytes } from "node:crypto";
46
46
  import { CacheManager } from "@databricks/appkit";
47
- import { env, log, object } from "@dbx-tools/shared-core";
48
- import { JWT_SECRET_ENV, SESSION_CUTOFF_ENV } from "./env.ts";
47
+ import { config } from "@dbx-tools/core";
48
+ import { log, object } from "@dbx-tools/shared-core";
49
+ import { TUNNEL_CONFIG } from "./_config.ts";
49
50
 
50
51
  const logger = log.logger("tunnel:signing-key");
51
52
 
@@ -85,12 +86,15 @@ interface StoredKey {
85
86
  * than not rotating.
86
87
  */
87
88
  export function resolveSessionCutoff(configured?: string | number | Date): number {
88
- const raw = configured ?? env.text(SESSION_CUTOFF_ENV) ?? undefined;
89
+ const raw =
90
+ configured ?? config.text(["AUTH_SESSION_CUTOFF", "AUTH_SESSION_EPOCH"], TUNNEL_CONFIG);
89
91
  if (raw === undefined || raw === null || raw === "") return 0;
90
92
 
91
93
  const date = object.toDate(raw);
92
94
  if (!date) {
93
- logger.warn(`ignoring unparseable ${env.name(SESSION_CUTOFF_ENV)}`, { value: String(raw) });
95
+ logger.warn(`ignoring unparseable ${config.name("AUTH_SESSION_CUTOFF", TUNNEL_CONFIG)}`, {
96
+ value: String(raw),
97
+ });
94
98
  return 0;
95
99
  }
96
100
  return clampToPast(date.getTime());
@@ -106,9 +110,12 @@ export function resolveSessionCutoff(configured?: string | number | Date): numbe
106
110
  function clampToPast(cutoffMs: number): number {
107
111
  const now = Date.now();
108
112
  if (cutoffMs <= now) return cutoffMs;
109
- logger.warn(`${env.name(SESSION_CUTOFF_ENV)} is in the future - clamping to now`, {
110
- configured: new Date(cutoffMs).toISOString(),
111
- });
113
+ logger.warn(
114
+ `${config.name("AUTH_SESSION_CUTOFF", TUNNEL_CONFIG)} is in the future - clamping to now`,
115
+ {
116
+ configured: new Date(cutoffMs).toISOString(),
117
+ },
118
+ );
112
119
  return now;
113
120
  }
114
121
 
@@ -178,7 +185,7 @@ let pending: Promise<SigningKey> | undefined;
178
185
  export function signingKey(configuredCutoff?: string | number | Date): Promise<SigningKey> {
179
186
  pending ??= (async () => {
180
187
  const cutoffMs = resolveSessionCutoff(configuredCutoff);
181
- const configured = env.text(JWT_SECRET_ENV);
188
+ const configured = config.text("AUTH_JWT_SECRET", TUNNEL_CONFIG);
182
189
  if (configured) {
183
190
  return { key: new TextEncoder().encode(configured), cutoffMs };
184
191
  }
@@ -186,7 +193,7 @@ export function signingKey(configuredCutoff?: string | number | Date): Promise<S
186
193
  return { key: await loadFromCache(cutoffMs), cutoffMs };
187
194
  } catch (error) {
188
195
  logger.warn(
189
- `no ${env.name(JWT_SECRET_ENV)} and the cache is unavailable - using an ephemeral per-process key; sessions will not survive a restart`,
196
+ `no ${config.name("AUTH_JWT_SECRET", TUNNEL_CONFIG)} and the cache is unavailable - using an ephemeral per-process key; sessions will not survive a restart`,
190
197
  { error },
191
198
  );
192
199
  return { key: new Uint8Array(randomBytes(KEY_BYTES)), cutoffMs };