@dbx-tools/cli-tunnel 0.6.48 → 0.6.50

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/README.md CHANGED
@@ -41,6 +41,11 @@ address against an allow-list, verified by a code sent over
41
41
  regex literal (`/^ops-.*@example\.com$/`). An empty list allows nobody.
42
42
  - Per-email and per-IP fixed-window rate limiting, plus anti-enumeration: a code
43
43
  request always answers `{ ok: true }`, whether or not the address is allowed.
44
+ - Inbound `x-` headers are stripped by default and re-allowed by pattern, so a
45
+ public caller cannot spoof the headers the app trusts - above all
46
+ `x-forwarded-access-token`, which would otherwise let anyone drive the app's
47
+ workspace calls with a pasted token. Add an app's own headers with
48
+ `--forward-headers`.
44
49
  - Platform traffic passes through UNGATED. The gate distinguishes the portr
45
50
  client (a loopback source address, same container) from the hosting platform's
46
51
  front door (a non-loopback container-network address), so health checks and the
@@ -87,23 +92,91 @@ original public port itself.
87
92
  Every flag has an environment fallback, so a deployment can configure the gate
88
93
  with no change to its start command.
89
94
 
90
- | Flag | Env | Default |
91
- | ----------------- | ------------------ | ---------------------------- |
92
- | `--allow` | `EMAIL_AUTH_ALLOW` | empty (allow nobody) |
93
- | `--subject` | `AUTH_SUBJECT` | `Your verification code` |
94
- | `--brand-name` | `AUTH_BRAND_NAME` | the brand context `name` |
95
- | `--message` | `AUTH_MESSAGE` | `Your verification code is:` |
96
- | `--session-ttl` | `AUTH_SESSION_TTL` | `43200` (12 hours) |
97
- | `--code-ttl` | `AUTH_CODE_TTL` | `600` (10 minutes) |
98
- | `--subdomain` | - | derived from `PUBLIC_DOMAIN` |
99
- | `--public-domain` | `PUBLIC_DOMAIN` | - |
100
- | `--insecure` | `TUNNEL_INSECURE` | off (the gate is required) |
101
-
102
- `--allow` and `EMAIL_AUTH_ALLOW` are UNIONED rather than one overriding the
95
+ | Flag | Env | Default |
96
+ | ------------------- | ------------------------- | ------------------------------ |
97
+ | `--allow` | `TUNNEL_AUTH_ALLOW` | empty (allow nobody) |
98
+ | `--subject` | `TUNNEL_AUTH_SUBJECT` | `Your verification code` |
99
+ | `--brand-name` | `TUNNEL_AUTH_BRAND_NAME` | the brand context `name` |
100
+ | `--message` | `TUNNEL_AUTH_MESSAGE` | `Your verification code is:` |
101
+ | `--session-ttl` | `TUNNEL_AUTH_SESSION_TTL` | `43200` (12 hours) |
102
+ | `--code-ttl` | `TUNNEL_AUTH_CODE_TTL` | `600` (10 minutes) |
103
+ | `--subdomain` | - | derived from the public domain |
104
+ | `--public-domain` | `TUNNEL_PUBLIC_DOMAIN` | - |
105
+ | `--forward-headers` | `TUNNEL_FORWARD_HEADERS` | the built-in `x-` allow-list |
106
+ | `--insecure` | `TUNNEL_INSECURE` | off (the gate is required) |
107
+ | - | `TUNNEL_AUTH_JWT_SECRET` | an ephemeral per-process key |
108
+
109
+ Every variable is `TUNNEL_`-prefixed because the gate runs as a WRAPPER: it and
110
+ the app it wraps share one environment, so a generic name is one the app may
111
+ already be using. The earlier unprefixed spellings - `AUTH_SUBJECT`,
112
+ `AUTH_BRAND_NAME`, `AUTH_MESSAGE`, `AUTH_SESSION_TTL`, `AUTH_CODE_TTL`,
113
+ `AUTH_JWT_SECRET`, `EMAIL_AUTH_ALLOW`, `PUBLIC_DOMAIN` - are still read as
114
+ deprecated aliases, with the `TUNNEL_` name winning when both are set, so an
115
+ existing deployment needs no coordinated rename. `PORTR_TOKEN` / `PORTR_SERVER`
116
+ keep their names: that namespace belongs to portr itself, as does
117
+ `DATABRICKS_APP_PORT`, which the platform sets and the gate honours.
118
+
119
+ `--allow` and `TUNNEL_AUTH_ALLOW` are UNIONED rather than one overriding the
103
120
  other, so a deployment-wide allow-list and a per-invocation addition both grant
104
- access. Session signing reads `AUTH_JWT_SECRET`; when it is unset the gate mints
105
- an ephemeral per-process key, so sessions simply do not survive a restart rather
106
- than the gate refusing to serve.
121
+ access. Session signing reads `TUNNEL_AUTH_JWT_SECRET`; when it is unset the gate
122
+ mints an ephemeral per-process key, so sessions simply do not survive a restart
123
+ rather than the gate refusing to serve. Set it in any deployment running more than
124
+ one instance, or a session minted by one will not verify on another.
125
+
126
+ ## Inbound Header Policy
127
+
128
+ Tunnel traffic arrives from the public internet, so every header on it is
129
+ attacker-controlled - and the headers an app trusts are exactly the ones a caller
130
+ must not be able to write, because the app cannot tell a header the Databricks
131
+ front door set from one a browser typed.
132
+
133
+ Enumerating headers to remove is a losing game (a deny-list is only correct until
134
+ the platform adds a header), so the policy is inverted: **every `x-`-prefixed
135
+ request header is stripped from tunnel traffic unless a pattern allows it.** A
136
+ header nobody thought about is removed rather than trusted. Non-`x-` headers -
137
+ `content-type`, `accept`, `authorization`, `cookie` - are the app's normal input
138
+ and pass through untouched.
139
+
140
+ The default allow-list covers the `x-` namespaces this repo's own client sends
141
+ and its own server reads, so a dbx-tools app works behind the tunnel with no
142
+ configuration:
143
+
144
+ | Pattern | Why |
145
+ | ------------------ | --------------------------------------------------- |
146
+ | `x-mastra-*` | thread and model routing for `@dbx-tools/ui-mastra` |
147
+ | `x-mlflow-*` | MLflow trace correlation for feedback |
148
+ | `x-requested-with` | the conventional AJAX marker |
149
+
150
+ Add an app's own headers with `--forward-headers` /`TUNNEL_FORWARD_HEADERS`. Each
151
+ entry is a literal name, a shell-style glob, or a `/regex/` - the same three
152
+ shapes the email allow-list takes - and the configured list is UNIONED with the
153
+ defaults, so extending it never silently breaks the built-in surfaces:
154
+
155
+ ```sh
156
+ dbxt-tunnel --forward-headers "x-acme-*, /^x-trace-/, x-tenant" -- bun src/server.ts
157
+ ```
158
+
159
+ Some headers no pattern can forward. These decide who a request is and where it
160
+ came from, and on tunnel traffic only the gate may answer that:
161
+
162
+ | Header | Why it is never forwarded |
163
+ | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
164
+ | `x-forwarded-access-token` | OBO auth. A pasted workspace token would make every call in the app run as its owner; a verified email proves nothing about who a credential belongs to. |
165
+ | `x-forwarded-user`, `-email` | Caller identity. The gate sets these itself, from a verified session. |
166
+ | `x-forwarded-preferred-username` | Display identity from the IdP. |
167
+ | `x-forwarded-host`, `-proto`, `-port` | Original host/scheme/port. Spoofing them poisons absolute URLs the app builds, or makes a plaintext request look like TLS. |
168
+ | `x-forwarded-for`, `x-real-ip` | Client IP. Spoofing forges the audit trail and gives a caller a fresh rate-limit bucket per request. |
169
+ | `x-request-id` | Request correlation UUID. Forged or colliding ids make logs unreliable. |
170
+
171
+ The identity headers are AppKit's OBO contract; the rest are the
172
+ [`X-Forwarded-*` set Databricks Apps documents passing to an
173
+ app](https://docs.databricks.com/aws/en/dev-tools/databricks-apps/http-headers),
174
+ plus the conventional `x-forwarded-proto`/`-port`/`x-real-ip` a library may read
175
+ anyway. Dropping the transport headers costs nothing: the proxy re-adds them from
176
+ the real socket after the policy runs, so the app sees the honest values instead
177
+ of the caller's claim. Rate limiting reads the client IP before stripping, and
178
+ takes the **rightmost** `x-forwarded-for` entry - the only one a proxy appended
179
+ rather than a client supplied.
107
180
 
108
181
  ## Use The Gate As A Plugin
109
182
 
@@ -156,10 +229,13 @@ by hand.
156
229
  - `proxy` - the public-port reverse proxy: loopback-vs-platform classification,
157
230
  open login routes, session enforcement, and WebSocket forwarding.
158
231
  - `otp` - the `CacheManager`-backed code store and the session JWT.
159
- - `allowlist` - domain / glob / regex matching and `looksLikeEmail`.
232
+ - `allowlist` - email domain / glob / regex matching and `looksLikeEmail`.
233
+ - `headers` - the inbound-header allow-list: `toHeaderPolicy()`,
234
+ `DEFAULT_FORWARD_HEADERS`, and the `PROTECTED_HEADERS` no pattern can forward.
160
235
  - `rate-limit` - the in-memory fixed-window limiter (single-instance only; not
161
236
  distributed).
162
237
  - `portr` - portr install, config rendering, and child launch.
238
+ - `env` - the environment-variable names, each with its deprecated aliases.
163
239
  - `app` - boots the minimal gate AppKit app and returns the `AuthGateApi`.
164
240
 
165
241
  Browser-safe login wire schemas (the request/verify payloads and the session
package/index.ts CHANGED
@@ -5,12 +5,17 @@
5
5
  export * as allowlist from "./src/allowlist.ts";
6
6
  export * as app from "./src/app.ts";
7
7
  export * as cli from "./src/cli.ts";
8
+ export * as env from "./src/env.ts";
9
+ export * as headers from "./src/headers.ts";
8
10
  export * as otp from "./src/otp.ts";
9
11
  export * as plugin from "./src/plugin.ts";
10
12
  export * as portr from "./src/portr.ts";
11
13
  export * as proxy from "./src/proxy.ts";
12
14
  export * as rateLimit from "./src/rate-limit.ts";
13
15
  export { CommanderError } from "./src/cli.ts";
16
+ export { ALLOW_ENV, SUBJECT_ENV, BRAND_NAME_ENV, MESSAGE_ENV, SESSION_TTL_ENV, CODE_TTL_ENV, JWT_SECRET_ENV, PUBLIC_DOMAIN_ENV, INSECURE_ENV, FORWARD_HEADERS_ENV } from "./src/env.ts";
17
+ export { PROTECTED_HEADERS, DEFAULT_FORWARD_HEADERS } from "./src/headers.ts";
18
+ export type { HeaderPolicy } from "./src/headers.ts";
14
19
  export { CodeStore } from "./src/otp.ts";
15
20
  export type { VerifyOutcome } from "./src/otp.ts";
16
21
  export { AuthGatePlugin, authGate } from "./src/plugin.ts";
package/lib/index.d.ts CHANGED
@@ -1,12 +1,17 @@
1
1
  export * as allowlist from "./src/allowlist.ts";
2
2
  export * as app from "./src/app.ts";
3
3
  export * as cli from "./src/cli.ts";
4
+ export * as env from "./src/env.ts";
5
+ export * as headers from "./src/headers.ts";
4
6
  export * as otp from "./src/otp.ts";
5
7
  export * as plugin from "./src/plugin.ts";
6
8
  export * as portr from "./src/portr.ts";
7
9
  export * as proxy from "./src/proxy.ts";
8
10
  export * as rateLimit from "./src/rate-limit.ts";
9
11
  export { CommanderError } from "./src/cli.ts";
12
+ export { ALLOW_ENV, SUBJECT_ENV, BRAND_NAME_ENV, MESSAGE_ENV, SESSION_TTL_ENV, CODE_TTL_ENV, JWT_SECRET_ENV, PUBLIC_DOMAIN_ENV, INSECURE_ENV, FORWARD_HEADERS_ENV } from "./src/env.ts";
13
+ export { PROTECTED_HEADERS, DEFAULT_FORWARD_HEADERS } from "./src/headers.ts";
14
+ export type { HeaderPolicy } from "./src/headers.ts";
10
15
  export { CodeStore } from "./src/otp.ts";
11
16
  export type { VerifyOutcome } from "./src/otp.ts";
12
17
  export { AuthGatePlugin, authGate } from "./src/plugin.ts";
package/lib/index.js CHANGED
@@ -4,13 +4,17 @@
4
4
  export * as allowlist from "./src/allowlist.js";
5
5
  export * as app from "./src/app.js";
6
6
  export * as cli from "./src/cli.js";
7
+ export * as env from "./src/env.js";
8
+ export * as headers from "./src/headers.js";
7
9
  export * as otp from "./src/otp.js";
8
10
  export * as plugin from "./src/plugin.js";
9
11
  export * as portr from "./src/portr.js";
10
12
  export * as proxy from "./src/proxy.js";
11
13
  export * as rateLimit from "./src/rate-limit.js";
12
14
  export { CommanderError } from "./src/cli.js";
15
+ export { ALLOW_ENV, SUBJECT_ENV, BRAND_NAME_ENV, MESSAGE_ENV, SESSION_TTL_ENV, CODE_TTL_ENV, JWT_SECRET_ENV, PUBLIC_DOMAIN_ENV, INSECURE_ENV, FORWARD_HEADERS_ENV } from "./src/env.js";
16
+ export { PROTECTED_HEADERS, DEFAULT_FORWARD_HEADERS } from "./src/headers.js";
13
17
  export { CodeStore } from "./src/otp.js";
14
18
  export { AuthGatePlugin, authGate } from "./src/plugin.js";
15
19
  export { RateLimiter } from "./src/rate-limit.js";
16
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxHQUFHLE1BQU0sY0FBYyxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxHQUFHLE1BQU0sY0FBYyxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxHQUFHLE1BQU0sY0FBYyxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLEtBQUssTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sS0FBSyxTQUFTLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUM5QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXpDLE9BQU8sRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFJM0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0ICogYXMgYWxsb3dsaXN0IGZyb20gXCIuL3NyYy9hbGxvd2xpc3QudHNcIjtcbmV4cG9ydCAqIGFzIGFwcCBmcm9tIFwiLi9zcmMvYXBwLnRzXCI7XG5leHBvcnQgKiBhcyBjbGkgZnJvbSBcIi4vc3JjL2NsaS50c1wiO1xuZXhwb3J0ICogYXMgb3RwIGZyb20gXCIuL3NyYy9vdHAudHNcIjtcbmV4cG9ydCAqIGFzIHBsdWdpbiBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG5leHBvcnQgKiBhcyBwb3J0ciBmcm9tIFwiLi9zcmMvcG9ydHIudHNcIjtcbmV4cG9ydCAqIGFzIHByb3h5IGZyb20gXCIuL3NyYy9wcm94eS50c1wiO1xuZXhwb3J0ICogYXMgcmF0ZUxpbWl0IGZyb20gXCIuL3NyYy9yYXRlLWxpbWl0LnRzXCI7XG5leHBvcnQgeyBDb21tYW5kZXJFcnJvciB9IGZyb20gXCIuL3NyYy9jbGkudHNcIjtcbmV4cG9ydCB7IENvZGVTdG9yZSB9IGZyb20gXCIuL3NyYy9vdHAudHNcIjtcbmV4cG9ydCB0eXBlIHsgVmVyaWZ5T3V0Y29tZSB9IGZyb20gXCIuL3NyYy9vdHAudHNcIjtcbmV4cG9ydCB7IEF1dGhHYXRlUGx1Z2luLCBhdXRoR2F0ZSB9IGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbmV4cG9ydCB0eXBlIHsgQXV0aEdhdGVDb25maWcsIFNlbmRDb2RlT3B0aW9ucywgUmVzb2x2ZWRBdXRoR2F0ZUNvbmZpZywgQXV0aEdhdGVBcGkgfSBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG5leHBvcnQgdHlwZSB7IFBvcnRyQ29uZmlnIH0gZnJvbSBcIi4vc3JjL3BvcnRyLnRzXCI7XG5leHBvcnQgdHlwZSB7IFByb3h5T3B0aW9ucyB9IGZyb20gXCIuL3NyYy9wcm94eS50c1wiO1xuZXhwb3J0IHsgUmF0ZUxpbWl0ZXIgfSBmcm9tIFwiLi9zcmMvcmF0ZS1saW1pdC50c1wiO1xuIl19
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxHQUFHLE1BQU0sY0FBYyxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxHQUFHLE1BQU0sY0FBYyxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxHQUFHLE1BQU0sY0FBYyxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxLQUFLLEdBQUcsTUFBTSxjQUFjLENBQUM7QUFDcEMsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sS0FBSyxLQUFLLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEMsT0FBTyxLQUFLLFNBQVMsTUFBTSxxQkFBcUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzlDLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsWUFBWSxFQUFFLG1CQUFtQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3hMLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRTlFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFekMsT0FBTyxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUkzRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgKiBhcyBhbGxvd2xpc3QgZnJvbSBcIi4vc3JjL2FsbG93bGlzdC50c1wiO1xuZXhwb3J0ICogYXMgYXBwIGZyb20gXCIuL3NyYy9hcHAudHNcIjtcbmV4cG9ydCAqIGFzIGNsaSBmcm9tIFwiLi9zcmMvY2xpLnRzXCI7XG5leHBvcnQgKiBhcyBlbnYgZnJvbSBcIi4vc3JjL2Vudi50c1wiO1xuZXhwb3J0ICogYXMgaGVhZGVycyBmcm9tIFwiLi9zcmMvaGVhZGVycy50c1wiO1xuZXhwb3J0ICogYXMgb3RwIGZyb20gXCIuL3NyYy9vdHAudHNcIjtcbmV4cG9ydCAqIGFzIHBsdWdpbiBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG5leHBvcnQgKiBhcyBwb3J0ciBmcm9tIFwiLi9zcmMvcG9ydHIudHNcIjtcbmV4cG9ydCAqIGFzIHByb3h5IGZyb20gXCIuL3NyYy9wcm94eS50c1wiO1xuZXhwb3J0ICogYXMgcmF0ZUxpbWl0IGZyb20gXCIuL3NyYy9yYXRlLWxpbWl0LnRzXCI7XG5leHBvcnQgeyBDb21tYW5kZXJFcnJvciB9IGZyb20gXCIuL3NyYy9jbGkudHNcIjtcbmV4cG9ydCB7IEFMTE9XX0VOViwgU1VCSkVDVF9FTlYsIEJSQU5EX05BTUVfRU5WLCBNRVNTQUdFX0VOViwgU0VTU0lPTl9UVExfRU5WLCBDT0RFX1RUTF9FTlYsIEpXVF9TRUNSRVRfRU5WLCBQVUJMSUNfRE9NQUlOX0VOViwgSU5TRUNVUkVfRU5WLCBGT1JXQVJEX0hFQURFUlNfRU5WIH0gZnJvbSBcIi4vc3JjL2Vudi50c1wiO1xuZXhwb3J0IHsgUFJPVEVDVEVEX0hFQURFUlMsIERFRkFVTFRfRk9SV0FSRF9IRUFERVJTIH0gZnJvbSBcIi4vc3JjL2hlYWRlcnMudHNcIjtcbmV4cG9ydCB0eXBlIHsgSGVhZGVyUG9saWN5IH0gZnJvbSBcIi4vc3JjL2hlYWRlcnMudHNcIjtcbmV4cG9ydCB7IENvZGVTdG9yZSB9IGZyb20gXCIuL3NyYy9vdHAudHNcIjtcbmV4cG9ydCB0eXBlIHsgVmVyaWZ5T3V0Y29tZSB9IGZyb20gXCIuL3NyYy9vdHAudHNcIjtcbmV4cG9ydCB7IEF1dGhHYXRlUGx1Z2luLCBhdXRoR2F0ZSB9IGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbmV4cG9ydCB0eXBlIHsgQXV0aEdhdGVDb25maWcsIFNlbmRDb2RlT3B0aW9ucywgUmVzb2x2ZWRBdXRoR2F0ZUNvbmZpZywgQXV0aEdhdGVBcGkgfSBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG5leHBvcnQgdHlwZSB7IFBvcnRyQ29uZmlnIH0gZnJvbSBcIi4vc3JjL3BvcnRyLnRzXCI7XG5leHBvcnQgdHlwZSB7IFByb3h5T3B0aW9ucyB9IGZyb20gXCIuL3NyYy9wcm94eS50c1wiO1xuZXhwb3J0IHsgUmF0ZUxpbWl0ZXIgfSBmcm9tIFwiLi9zcmMvcmF0ZS1saW1pdC50c1wiO1xuIl19
@@ -1,17 +1,22 @@
1
1
  /**
2
2
  * Unified access allow-list matching for the email-OTP gate.
3
3
  *
4
- * Each pattern in the configured list is one of three shapes, tried in order:
4
+ * Each pattern in the configured list is one of three shapes:
5
5
  *
6
6
  * - **domain shortcut** - `example.com` or `@example.com`: matches any
7
- * address whose domain equals it (case-insensitive). The leading `@` is
8
- * optional and stripped.
9
- * - **glob** - contains `*` or `?`, e.g. `*.example.com` or
10
- * `*@example.com`: matched against the WHOLE address with shell-style
11
- * wildcards (`*` = any run, `?` = one char).
12
- * - **regex** - wrapped in slashes, `/.../ [flags]`: compiled and tested
13
- * against the whole address. An invalid regex never matches (it is skipped
14
- * with a warning rather than throwing).
7
+ * address whose domain equals it. This is the gate's OWN semantic (a bare
8
+ * value means "the domain", not "the whole address"), so it is handled here.
9
+ * - **glob** - contains `*` or `?`, e.g. `*@example.com`: matched against the
10
+ * WHOLE address with shell-style wildcards.
11
+ * - **regex** - wrapped in slashes, `/.../ [flags]`: tested against the whole
12
+ * address. An invalid regex never matches (it is skipped with a warning
13
+ * rather than throwing).
14
+ *
15
+ * Only the first shape is this module's business: the glob and regex shapes are
16
+ * delegated to `@dbx-tools/shared-core`'s {@link pattern.toPattern}, which is
17
+ * where that compilation lives for every allow-list in the repo (the tunnel's
18
+ * inbound-header policy uses the same one). Matching is case-insensitive
19
+ * throughout.
15
20
  *
16
21
  * An EMPTY list matches nobody (fail closed): an app that enables the gate but
17
22
  * configures no patterns lets no one in, which is the safe default.
@@ -1,70 +1,45 @@
1
1
  /**
2
2
  * Unified access allow-list matching for the email-OTP gate.
3
3
  *
4
- * Each pattern in the configured list is one of three shapes, tried in order:
4
+ * Each pattern in the configured list is one of three shapes:
5
5
  *
6
6
  * - **domain shortcut** - `example.com` or `@example.com`: matches any
7
- * address whose domain equals it (case-insensitive). The leading `@` is
8
- * optional and stripped.
9
- * - **glob** - contains `*` or `?`, e.g. `*.example.com` or
10
- * `*@example.com`: matched against the WHOLE address with shell-style
11
- * wildcards (`*` = any run, `?` = one char).
12
- * - **regex** - wrapped in slashes, `/.../ [flags]`: compiled and tested
13
- * against the whole address. An invalid regex never matches (it is skipped
14
- * with a warning rather than throwing).
7
+ * address whose domain equals it. This is the gate's OWN semantic (a bare
8
+ * value means "the domain", not "the whole address"), so it is handled here.
9
+ * - **glob** - contains `*` or `?`, e.g. `*@example.com`: matched against the
10
+ * WHOLE address with shell-style wildcards.
11
+ * - **regex** - wrapped in slashes, `/.../ [flags]`: tested against the whole
12
+ * address. An invalid regex never matches (it is skipped with a warning
13
+ * rather than throwing).
14
+ *
15
+ * Only the first shape is this module's business: the glob and regex shapes are
16
+ * delegated to `@dbx-tools/shared-core`'s {@link pattern.toPattern}, which is
17
+ * where that compilation lives for every allow-list in the repo (the tunnel's
18
+ * inbound-header policy uses the same one). Matching is case-insensitive
19
+ * throughout.
15
20
  *
16
21
  * An EMPTY list matches nobody (fail closed): an app that enables the gate but
17
22
  * configures no patterns lets no one in, which is the safe default.
18
23
  *
19
24
  * @module
20
25
  */
21
- import { log } from "@dbx-tools/shared-core";
22
- const logger = log.logger("tunnel:allowlist");
23
- /** Escape a string for literal use inside a `RegExp`. */
24
- function escapeRegExp(value) {
25
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26
- }
27
- /** Compile a shell-style glob (`*`, `?`) into an anchored, case-insensitive RegExp. */
28
- function globToRegExp(glob) {
29
- const body = glob
30
- .split(/([*?])/)
31
- .map((part) => (part === "*" ? ".*" : part === "?" ? "." : escapeRegExp(part)))
32
- .join("");
33
- return new RegExp(`^${body}$`, "i");
34
- }
35
- /** Parse a `/pattern/flags` string into a RegExp, or `undefined` if malformed. */
36
- function parseRegexLiteral(pattern) {
37
- const match = /^\/(.+)\/([a-z]*)$/is.exec(pattern);
38
- if (!match)
39
- return undefined;
40
- try {
41
- const flags = match[2].includes("i") ? match[2] : `${match[2]}i`;
42
- return new RegExp(match[1], flags);
43
- }
44
- catch (error) {
45
- logger.warn("ignoring invalid regex allow-list pattern", { pattern, error });
46
- return undefined;
47
- }
48
- }
26
+ import { pattern } from "@dbx-tools/shared-core";
49
27
  /** True when `email` matches a single allow-list `pattern`. */
50
- function matchesPattern(email, pattern) {
51
- const trimmed = pattern.trim();
28
+ function matchesPattern(email, entry) {
29
+ const trimmed = entry.trim();
52
30
  if (!trimmed)
53
31
  return false;
54
32
  const address = email.trim().toLowerCase();
55
- // Regex literal: /.../
56
- if (trimmed.startsWith("/")) {
57
- const re = parseRegexLiteral(trimmed);
58
- return re ? re.test(address) : false;
59
- }
60
- // Glob: contains a wildcard.
61
- if (trimmed.includes("*") || trimmed.includes("?")) {
62
- return globToRegExp(trimmed).test(address);
33
+ // A bare value with no wildcard and no regex delimiters is a DOMAIN shortcut,
34
+ // the one shape shared-core cannot infer: there it would mean whole-string
35
+ // equality against the address, which is never what an operator writing
36
+ // `example.com` in an access list intends.
37
+ if (!trimmed.startsWith("/") && !trimmed.includes("*") && !trimmed.includes("?")) {
38
+ const domain = trimmed.replace(/^@/, "").toLowerCase();
39
+ const at = address.lastIndexOf("@");
40
+ return at >= 0 && address.slice(at + 1) === domain;
63
41
  }
64
- // Domain shortcut: `@d.com` or `d.com` -> match the address's domain.
65
- const domain = trimmed.replace(/^@/, "").toLowerCase();
66
- const at = address.lastIndexOf("@");
67
- return at >= 0 && address.slice(at + 1) === domain;
42
+ return pattern.toPattern(trimmed)?.(address) ?? false;
68
43
  }
69
44
  /**
70
45
  * True when `email` is allowed by ANY pattern in `patterns`. An empty (or
@@ -73,10 +48,10 @@ function matchesPattern(email, pattern) {
73
48
  export function matchesAllowlist(email, patterns) {
74
49
  if (!email || !patterns || patterns.length === 0)
75
50
  return false;
76
- return patterns.some((pattern) => matchesPattern(email, pattern));
51
+ return patterns.some((entry) => matchesPattern(email, entry));
77
52
  }
78
53
  /** Rough shape check so a clearly-invalid address is rejected before any work. */
79
54
  export function looksLikeEmail(value) {
80
55
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
81
56
  }
82
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxsb3dsaXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FsbG93bGlzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUVILE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU3QyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7QUFFOUMseURBQXlEO0FBQ3pELFNBQVMsWUFBWSxDQUFDLEtBQWE7SUFDakMsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ3RELENBQUM7QUFFRCx1RkFBdUY7QUFDdkYsU0FBUyxZQUFZLENBQUMsSUFBWTtJQUNoQyxNQUFNLElBQUksR0FBRyxJQUFJO1NBQ2QsS0FBSyxDQUFDLFFBQVEsQ0FBQztTQUNmLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7U0FDOUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ1osT0FBTyxJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ3RDLENBQUM7QUFFRCxrRkFBa0Y7QUFDbEYsU0FBUyxpQkFBaUIsQ0FBQyxPQUFlO0lBQ3hDLE1BQU0sS0FBSyxHQUFHLHNCQUFzQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuRCxJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQzdCLElBQUksQ0FBQztRQUNILE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFFLEdBQUcsQ0FBQztRQUNwRSxPQUFPLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE1BQU0sQ0FBQyxJQUFJLENBQUMsMkNBQTJDLEVBQUUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUM3RSxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQztBQUVELCtEQUErRDtBQUMvRCxTQUFTLGNBQWMsQ0FBQyxLQUFhLEVBQUUsT0FBZTtJQUNwRCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDL0IsSUFBSSxDQUFDLE9BQU87UUFBRSxPQUFPLEtBQUssQ0FBQztJQUMzQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFM0MsdUJBQXVCO0lBQ3ZCLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzVCLE1BQU0sRUFBRSxHQUFHLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3RDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDdkMsQ0FBQztJQUVELDZCQUE2QjtJQUM3QixJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ25ELE9BQU8sWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQsc0VBQXNFO0lBQ3RFLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3ZELE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDcEMsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQztBQUNyRCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEtBQWEsRUFBRSxRQUF1QztJQUNyRixJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQy9ELE9BQU8sUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQ3BFLENBQUM7QUFFRCxrRkFBa0Y7QUFDbEYsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUFhO0lBQzFDLE9BQU8sNEJBQTRCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFVuaWZpZWQgYWNjZXNzIGFsbG93LWxpc3QgbWF0Y2hpbmcgZm9yIHRoZSBlbWFpbC1PVFAgZ2F0ZS5cbiAqXG4gKiBFYWNoIHBhdHRlcm4gaW4gdGhlIGNvbmZpZ3VyZWQgbGlzdCBpcyBvbmUgb2YgdGhyZWUgc2hhcGVzLCB0cmllZCBpbiBvcmRlcjpcbiAqXG4gKiAgIC0gKipkb21haW4gc2hvcnRjdXQqKiAtIGBleGFtcGxlLmNvbWAgb3IgYEBleGFtcGxlLmNvbWA6IG1hdGNoZXMgYW55XG4gKiAgICAgYWRkcmVzcyB3aG9zZSBkb21haW4gZXF1YWxzIGl0IChjYXNlLWluc2Vuc2l0aXZlKS4gVGhlIGxlYWRpbmcgYEBgIGlzXG4gKiAgICAgb3B0aW9uYWwgYW5kIHN0cmlwcGVkLlxuICogICAtICoqZ2xvYioqIC0gY29udGFpbnMgYCpgIG9yIGA/YCwgZS5nLiBgKi5leGFtcGxlLmNvbWAgb3JcbiAqICAgICBgKkBleGFtcGxlLmNvbWA6IG1hdGNoZWQgYWdhaW5zdCB0aGUgV0hPTEUgYWRkcmVzcyB3aXRoIHNoZWxsLXN0eWxlXG4gKiAgICAgd2lsZGNhcmRzIChgKmAgPSBhbnkgcnVuLCBgP2AgPSBvbmUgY2hhcikuXG4gKiAgIC0gKipyZWdleCoqIC0gd3JhcHBlZCBpbiBzbGFzaGVzLCBgLy4uLi8gW2ZsYWdzXWA6IGNvbXBpbGVkIGFuZCB0ZXN0ZWRcbiAqICAgICBhZ2FpbnN0IHRoZSB3aG9sZSBhZGRyZXNzLiBBbiBpbnZhbGlkIHJlZ2V4IG5ldmVyIG1hdGNoZXMgKGl0IGlzIHNraXBwZWRcbiAqICAgICB3aXRoIGEgd2FybmluZyByYXRoZXIgdGhhbiB0aHJvd2luZykuXG4gKlxuICogQW4gRU1QVFkgbGlzdCBtYXRjaGVzIG5vYm9keSAoZmFpbCBjbG9zZWQpOiBhbiBhcHAgdGhhdCBlbmFibGVzIHRoZSBnYXRlIGJ1dFxuICogY29uZmlndXJlcyBubyBwYXR0ZXJucyBsZXRzIG5vIG9uZSBpbiwgd2hpY2ggaXMgdGhlIHNhZmUgZGVmYXVsdC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcInR1bm5lbDphbGxvd2xpc3RcIik7XG5cbi8qKiBFc2NhcGUgYSBzdHJpbmcgZm9yIGxpdGVyYWwgdXNlIGluc2lkZSBhIGBSZWdFeHBgLiAqL1xuZnVuY3Rpb24gZXNjYXBlUmVnRXhwKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gdmFsdWUucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csIFwiXFxcXCQmXCIpO1xufVxuXG4vKiogQ29tcGlsZSBhIHNoZWxsLXN0eWxlIGdsb2IgKGAqYCwgYD9gKSBpbnRvIGFuIGFuY2hvcmVkLCBjYXNlLWluc2Vuc2l0aXZlIFJlZ0V4cC4gKi9cbmZ1bmN0aW9uIGdsb2JUb1JlZ0V4cChnbG9iOiBzdHJpbmcpOiBSZWdFeHAge1xuICBjb25zdCBib2R5ID0gZ2xvYlxuICAgIC5zcGxpdCgvKFsqP10pLylcbiAgICAubWFwKChwYXJ0KSA9PiAocGFydCA9PT0gXCIqXCIgPyBcIi4qXCIgOiBwYXJ0ID09PSBcIj9cIiA/IFwiLlwiIDogZXNjYXBlUmVnRXhwKHBhcnQpKSlcbiAgICAuam9pbihcIlwiKTtcbiAgcmV0dXJuIG5ldyBSZWdFeHAoYF4ke2JvZHl9JGAsIFwiaVwiKTtcbn1cblxuLyoqIFBhcnNlIGEgYC9wYXR0ZXJuL2ZsYWdzYCBzdHJpbmcgaW50byBhIFJlZ0V4cCwgb3IgYHVuZGVmaW5lZGAgaWYgbWFsZm9ybWVkLiAqL1xuZnVuY3Rpb24gcGFyc2VSZWdleExpdGVyYWwocGF0dGVybjogc3RyaW5nKTogUmVnRXhwIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgbWF0Y2ggPSAvXlxcLyguKylcXC8oW2Etel0qKSQvaXMuZXhlYyhwYXR0ZXJuKTtcbiAgaWYgKCFtYXRjaCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgdHJ5IHtcbiAgICBjb25zdCBmbGFncyA9IG1hdGNoWzJdIS5pbmNsdWRlcyhcImlcIikgPyBtYXRjaFsyXSEgOiBgJHttYXRjaFsyXSF9aWA7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAobWF0Y2hbMV0hLCBmbGFncyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgbG9nZ2VyLndhcm4oXCJpZ25vcmluZyBpbnZhbGlkIHJlZ2V4IGFsbG93LWxpc3QgcGF0dGVyblwiLCB7IHBhdHRlcm4sIGVycm9yIH0pO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqIFRydWUgd2hlbiBgZW1haWxgIG1hdGNoZXMgYSBzaW5nbGUgYWxsb3ctbGlzdCBgcGF0dGVybmAuICovXG5mdW5jdGlvbiBtYXRjaGVzUGF0dGVybihlbWFpbDogc3RyaW5nLCBwYXR0ZXJuOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgdHJpbW1lZCA9IHBhdHRlcm4udHJpbSgpO1xuICBpZiAoIXRyaW1tZWQpIHJldHVybiBmYWxzZTtcbiAgY29uc3QgYWRkcmVzcyA9IGVtYWlsLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuXG4gIC8vIFJlZ2V4IGxpdGVyYWw6IC8uLi4vXG4gIGlmICh0cmltbWVkLnN0YXJ0c1dpdGgoXCIvXCIpKSB7XG4gICAgY29uc3QgcmUgPSBwYXJzZVJlZ2V4TGl0ZXJhbCh0cmltbWVkKTtcbiAgICByZXR1cm4gcmUgPyByZS50ZXN0KGFkZHJlc3MpIDogZmFsc2U7XG4gIH1cblxuICAvLyBHbG9iOiBjb250YWlucyBhIHdpbGRjYXJkLlxuICBpZiAodHJpbW1lZC5pbmNsdWRlcyhcIipcIikgfHwgdHJpbW1lZC5pbmNsdWRlcyhcIj9cIikpIHtcbiAgICByZXR1cm4gZ2xvYlRvUmVnRXhwKHRyaW1tZWQpLnRlc3QoYWRkcmVzcyk7XG4gIH1cblxuICAvLyBEb21haW4gc2hvcnRjdXQ6IGBAZC5jb21gIG9yIGBkLmNvbWAgLT4gbWF0Y2ggdGhlIGFkZHJlc3MncyBkb21haW4uXG4gIGNvbnN0IGRvbWFpbiA9IHRyaW1tZWQucmVwbGFjZSgvXkAvLCBcIlwiKS50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBhdCA9IGFkZHJlc3MubGFzdEluZGV4T2YoXCJAXCIpO1xuICByZXR1cm4gYXQgPj0gMCAmJiBhZGRyZXNzLnNsaWNlKGF0ICsgMSkgPT09IGRvbWFpbjtcbn1cblxuLyoqXG4gKiBUcnVlIHdoZW4gYGVtYWlsYCBpcyBhbGxvd2VkIGJ5IEFOWSBwYXR0ZXJuIGluIGBwYXR0ZXJuc2AuIEFuIGVtcHR5IChvclxuICogbWlzc2luZykgbGlzdCBhbGxvd3Mgbm9ib2R5IC0gdGhlIGdhdGUgZmFpbHMgY2xvc2VkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2hlc0FsbG93bGlzdChlbWFpbDogc3RyaW5nLCBwYXR0ZXJuczogcmVhZG9ubHkgc3RyaW5nW10gfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgaWYgKCFlbWFpbCB8fCAhcGF0dGVybnMgfHwgcGF0dGVybnMubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiBwYXR0ZXJucy5zb21lKChwYXR0ZXJuKSA9PiBtYXRjaGVzUGF0dGVybihlbWFpbCwgcGF0dGVybikpO1xufVxuXG4vKiogUm91Z2ggc2hhcGUgY2hlY2sgc28gYSBjbGVhcmx5LWludmFsaWQgYWRkcmVzcyBpcyByZWplY3RlZCBiZWZvcmUgYW55IHdvcmsuICovXG5leHBvcnQgZnVuY3Rpb24gbG9va3NMaWtlRW1haWwodmFsdWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gL15bXlxcc0BdK0BbXlxcc0BdK1xcLlteXFxzQF0rJC8udGVzdCh2YWx1ZS50cmltKCkpO1xufVxuIl19
57
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxsb3dsaXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FsbG93bGlzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBRUgsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRWpELCtEQUErRDtBQUMvRCxTQUFTLGNBQWMsQ0FBQyxLQUFhLEVBQUUsS0FBYTtJQUNsRCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDN0IsSUFBSSxDQUFDLE9BQU87UUFBRSxPQUFPLEtBQUssQ0FBQztJQUMzQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFM0MsOEVBQThFO0lBQzlFLDJFQUEyRTtJQUMzRSx3RUFBd0U7SUFDeEUsMkNBQTJDO0lBQzNDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNqRixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN2RCxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BDLE9BQU8sRUFBRSxJQUFJLENBQUMsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsS0FBSyxNQUFNLENBQUM7SUFDckQsQ0FBQztJQUVELE9BQU8sT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssQ0FBQztBQUN4RCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEtBQWEsRUFBRSxRQUF1QztJQUNyRixJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQy9ELE9BQU8sUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFFRCxrRkFBa0Y7QUFDbEYsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUFhO0lBQzFDLE9BQU8sNEJBQTRCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFVuaWZpZWQgYWNjZXNzIGFsbG93LWxpc3QgbWF0Y2hpbmcgZm9yIHRoZSBlbWFpbC1PVFAgZ2F0ZS5cbiAqXG4gKiBFYWNoIHBhdHRlcm4gaW4gdGhlIGNvbmZpZ3VyZWQgbGlzdCBpcyBvbmUgb2YgdGhyZWUgc2hhcGVzOlxuICpcbiAqICAgLSAqKmRvbWFpbiBzaG9ydGN1dCoqIC0gYGV4YW1wbGUuY29tYCBvciBgQGV4YW1wbGUuY29tYDogbWF0Y2hlcyBhbnlcbiAqICAgICBhZGRyZXNzIHdob3NlIGRvbWFpbiBlcXVhbHMgaXQuIFRoaXMgaXMgdGhlIGdhdGUncyBPV04gc2VtYW50aWMgKGEgYmFyZVxuICogICAgIHZhbHVlIG1lYW5zIFwidGhlIGRvbWFpblwiLCBub3QgXCJ0aGUgd2hvbGUgYWRkcmVzc1wiKSwgc28gaXQgaXMgaGFuZGxlZCBoZXJlLlxuICogICAtICoqZ2xvYioqIC0gY29udGFpbnMgYCpgIG9yIGA/YCwgZS5nLiBgKkBleGFtcGxlLmNvbWA6IG1hdGNoZWQgYWdhaW5zdCB0aGVcbiAqICAgICBXSE9MRSBhZGRyZXNzIHdpdGggc2hlbGwtc3R5bGUgd2lsZGNhcmRzLlxuICogICAtICoqcmVnZXgqKiAtIHdyYXBwZWQgaW4gc2xhc2hlcywgYC8uLi4vIFtmbGFnc11gOiB0ZXN0ZWQgYWdhaW5zdCB0aGUgd2hvbGVcbiAqICAgICBhZGRyZXNzLiBBbiBpbnZhbGlkIHJlZ2V4IG5ldmVyIG1hdGNoZXMgKGl0IGlzIHNraXBwZWQgd2l0aCBhIHdhcm5pbmdcbiAqICAgICByYXRoZXIgdGhhbiB0aHJvd2luZykuXG4gKlxuICogT25seSB0aGUgZmlyc3Qgc2hhcGUgaXMgdGhpcyBtb2R1bGUncyBidXNpbmVzczogdGhlIGdsb2IgYW5kIHJlZ2V4IHNoYXBlcyBhcmVcbiAqIGRlbGVnYXRlZCB0byBgQGRieC10b29scy9zaGFyZWQtY29yZWAncyB7QGxpbmsgcGF0dGVybi50b1BhdHRlcm59LCB3aGljaCBpc1xuICogd2hlcmUgdGhhdCBjb21waWxhdGlvbiBsaXZlcyBmb3IgZXZlcnkgYWxsb3ctbGlzdCBpbiB0aGUgcmVwbyAodGhlIHR1bm5lbCdzXG4gKiBpbmJvdW5kLWhlYWRlciBwb2xpY3kgdXNlcyB0aGUgc2FtZSBvbmUpLiBNYXRjaGluZyBpcyBjYXNlLWluc2Vuc2l0aXZlXG4gKiB0aHJvdWdob3V0LlxuICpcbiAqIEFuIEVNUFRZIGxpc3QgbWF0Y2hlcyBub2JvZHkgKGZhaWwgY2xvc2VkKTogYW4gYXBwIHRoYXQgZW5hYmxlcyB0aGUgZ2F0ZSBidXRcbiAqIGNvbmZpZ3VyZXMgbm8gcGF0dGVybnMgbGV0cyBubyBvbmUgaW4sIHdoaWNoIGlzIHRoZSBzYWZlIGRlZmF1bHQuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IHBhdHRlcm4gfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuXG4vKiogVHJ1ZSB3aGVuIGBlbWFpbGAgbWF0Y2hlcyBhIHNpbmdsZSBhbGxvdy1saXN0IGBwYXR0ZXJuYC4gKi9cbmZ1bmN0aW9uIG1hdGNoZXNQYXR0ZXJuKGVtYWlsOiBzdHJpbmcsIGVudHJ5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgdHJpbW1lZCA9IGVudHJ5LnRyaW0oKTtcbiAgaWYgKCF0cmltbWVkKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IGFkZHJlc3MgPSBlbWFpbC50cmltKCkudG9Mb3dlckNhc2UoKTtcblxuICAvLyBBIGJhcmUgdmFsdWUgd2l0aCBubyB3aWxkY2FyZCBhbmQgbm8gcmVnZXggZGVsaW1pdGVycyBpcyBhIERPTUFJTiBzaG9ydGN1dCxcbiAgLy8gdGhlIG9uZSBzaGFwZSBzaGFyZWQtY29yZSBjYW5ub3QgaW5mZXI6IHRoZXJlIGl0IHdvdWxkIG1lYW4gd2hvbGUtc3RyaW5nXG4gIC8vIGVxdWFsaXR5IGFnYWluc3QgdGhlIGFkZHJlc3MsIHdoaWNoIGlzIG5ldmVyIHdoYXQgYW4gb3BlcmF0b3Igd3JpdGluZ1xuICAvLyBgZXhhbXBsZS5jb21gIGluIGFuIGFjY2VzcyBsaXN0IGludGVuZHMuXG4gIGlmICghdHJpbW1lZC5zdGFydHNXaXRoKFwiL1wiKSAmJiAhdHJpbW1lZC5pbmNsdWRlcyhcIipcIikgJiYgIXRyaW1tZWQuaW5jbHVkZXMoXCI/XCIpKSB7XG4gICAgY29uc3QgZG9tYWluID0gdHJpbW1lZC5yZXBsYWNlKC9eQC8sIFwiXCIpLnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3QgYXQgPSBhZGRyZXNzLmxhc3RJbmRleE9mKFwiQFwiKTtcbiAgICByZXR1cm4gYXQgPj0gMCAmJiBhZGRyZXNzLnNsaWNlKGF0ICsgMSkgPT09IGRvbWFpbjtcbiAgfVxuXG4gIHJldHVybiBwYXR0ZXJuLnRvUGF0dGVybih0cmltbWVkKT8uKGFkZHJlc3MpID8/IGZhbHNlO1xufVxuXG4vKipcbiAqIFRydWUgd2hlbiBgZW1haWxgIGlzIGFsbG93ZWQgYnkgQU5ZIHBhdHRlcm4gaW4gYHBhdHRlcm5zYC4gQW4gZW1wdHkgKG9yXG4gKiBtaXNzaW5nKSBsaXN0IGFsbG93cyBub2JvZHkgLSB0aGUgZ2F0ZSBmYWlscyBjbG9zZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaGVzQWxsb3dsaXN0KGVtYWlsOiBzdHJpbmcsIHBhdHRlcm5zOiByZWFkb25seSBzdHJpbmdbXSB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICBpZiAoIWVtYWlsIHx8ICFwYXR0ZXJucyB8fCBwYXR0ZXJucy5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHBhdHRlcm5zLnNvbWUoKGVudHJ5KSA9PiBtYXRjaGVzUGF0dGVybihlbWFpbCwgZW50cnkpKTtcbn1cblxuLyoqIFJvdWdoIHNoYXBlIGNoZWNrIHNvIGEgY2xlYXJseS1pbnZhbGlkIGFkZHJlc3MgaXMgcmVqZWN0ZWQgYmVmb3JlIGFueSB3b3JrLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvb2tzTGlrZUVtYWlsKHZhbHVlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9eW15cXHNAXStAW15cXHNAXStcXC5bXlxcc0BdKyQvLnRlc3QodmFsdWUudHJpbSgpKTtcbn1cbiJdfQ==
package/lib/src/cli.js CHANGED
@@ -25,9 +25,10 @@
25
25
  * @module
26
26
  */
27
27
  import { spawn } from "node:child_process";
28
- import { log } from "@dbx-tools/shared-core";
28
+ import { env, log } from "@dbx-tools/shared-core";
29
29
  import { Command, CommanderError } from "commander";
30
30
  import { startGateApp } from "./app.js";
31
+ import { FORWARD_HEADERS_ENV, INSECURE_ENV } from "./env.js";
31
32
  import { installPortr, resolvePortrConfig, startPortr, writePortrConfig } from "./portr.js";
32
33
  import { startProxy } from "./proxy.js";
33
34
  export { CommanderError };
@@ -41,14 +42,15 @@ function program() {
41
42
  return new Command()
42
43
  .name("dbx-tools-tunnel")
43
44
  .description("Front an app with a public portr tunnel + email-OTP gate")
44
- .option("--subject <text>", "Subject line for the code email (env AUTH_SUBJECT)")
45
- .option("--allow <patterns>", "Comma/space-separated allow-list: domain / glob / /regex/ (env EMAIL_AUTH_ALLOW)")
46
- .option("--subdomain <name>", "portr subdomain (else derived from PUBLIC_DOMAIN)")
47
- .option("--public-domain <host>", "portr <subdomain>.<server> (env PUBLIC_DOMAIN)")
48
- .option("--brand-name <name>", "Display name in the code email copy (env AUTH_BRAND_NAME; defaults to the brand context name)")
49
- .option("--message <text>", "Line shown above the code in the email (env AUTH_MESSAGE)")
50
- .option("--session-ttl <seconds>", "Session lifetime (env AUTH_SESSION_TTL)")
51
- .option("--code-ttl <seconds>", "One-time-code lifetime (env AUTH_CODE_TTL)")
45
+ .option("--subject <text>", "Subject line for the code email (env TUNNEL_AUTH_SUBJECT)")
46
+ .option("--allow <patterns>", "Comma/space-separated allow-list: domain / glob / /regex/ (env TUNNEL_AUTH_ALLOW)")
47
+ .option("--subdomain <name>", "portr subdomain (else derived from TUNNEL_PUBLIC_DOMAIN)")
48
+ .option("--public-domain <host>", "portr <subdomain>.<server> (env TUNNEL_PUBLIC_DOMAIN)")
49
+ .option("--brand-name <name>", "Display name in the code email copy (env TUNNEL_AUTH_BRAND_NAME; defaults to the brand context name)")
50
+ .option("--message <text>", "Line shown above the code in the email (env TUNNEL_AUTH_MESSAGE)")
51
+ .option("--session-ttl <seconds>", "Session lifetime (env TUNNEL_AUTH_SESSION_TTL)")
52
+ .option("--code-ttl <seconds>", "One-time-code lifetime (env TUNNEL_AUTH_CODE_TTL)")
53
+ .option("--forward-headers <patterns>", "Extra x- request headers tunnel traffic may forward: literal / glob / /regex/ (env TUNNEL_FORWARD_HEADERS)")
52
54
  .option("--insecure", "Run the tunnel OPEN with no gate (env TUNNEL_INSECURE=true). Otherwise the CLI fails fast when email SMTP is not configured.")
53
55
  .allowExcessArguments(true)
54
56
  .helpOption("-h, --help", "Show help");
@@ -110,7 +112,7 @@ export async function runCli(argv) {
110
112
  // 2. Boot the gate app (cache + email transport + gate API). `startGateApp`
111
113
  // FAILS FAST when email can't send codes (no SMTP). Insecure mode
112
114
  // (`--insecure` / TUNNEL_INSECURE) skips the gate and runs the tunnel open.
113
- const insecure = opts.insecure || /^(1|true|yes|on)$/i.test(process.env.TUNNEL_INSECURE ?? "");
115
+ const insecure = env.boolean(opts.insecure, INSECURE_ENV) ?? false;
114
116
  let gate;
115
117
  if (insecure) {
116
118
  logger.warn("insecure mode - tunnel runs OPEN with no email-OTP gate");
@@ -127,7 +129,13 @@ export async function runCli(argv) {
127
129
  }
128
130
  }
129
131
  // 3. Start the gate proxy on the public port (open when `gate` is undefined).
130
- await startProxy({ publicPort, appPort, gate });
132
+ // `forwardHeaders` only ADDS to the built-in allow-list; see `./headers.ts`.
133
+ await startProxy({
134
+ publicPort,
135
+ appPort,
136
+ gate,
137
+ forwardHeaders: env.list(opts.forwardHeaders, FORWARD_HEADERS_ENV),
138
+ });
131
139
  // 4. Install + run portr when a tunnel is configured.
132
140
  const portrConfig = resolvePortrConfig({
133
141
  publicDomain: opts.publicDomain,
@@ -136,14 +144,14 @@ export async function runCli(argv) {
136
144
  });
137
145
  const children = [app];
138
146
  if (portrConfig) {
139
- const env = installPortr();
140
- writePortrConfig(portrConfig, env);
141
- children.push(startPortr(portrConfig, env));
147
+ const portrEnv = installPortr();
148
+ writePortrConfig(portrConfig, portrEnv);
149
+ children.push(startPortr(portrConfig, portrEnv));
142
150
  }
143
151
  else {
144
- logger.info("no PORTR_TOKEN/PUBLIC_DOMAIN - serving the gate proxy without a public tunnel");
152
+ logger.info("no PORTR_TOKEN/TUNNEL_PUBLIC_DOMAIN - serving the gate proxy without a public tunnel");
145
153
  }
146
154
  // Any child exit (or a signal) tears the whole thing down.
147
155
  superviseExit(children);
148
156
  }
149
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlCRztBQUVILE9BQU8sRUFBcUIsS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDOUQsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzdDLE9BQU8sRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDNUYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV4QyxPQUFPLEVBQUUsY0FBYyxFQUFFLENBQUM7QUFFMUIsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUVwQyxxRkFBcUY7QUFDckYsU0FBUyxVQUFVO0lBQ2pCLE9BQU8sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFjRCxvRkFBb0Y7QUFDcEYsU0FBUyxPQUFPO0lBQ2QsT0FBTyxJQUFJLE9BQU8sRUFBRTtTQUNqQixJQUFJLENBQUMsa0JBQWtCLENBQUM7U0FDeEIsV0FBVyxDQUFDLDBEQUEwRCxDQUFDO1NBQ3ZFLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxvREFBb0QsQ0FBQztTQUNoRixNQUFNLENBQ0wsb0JBQW9CLEVBQ3BCLGtGQUFrRixDQUNuRjtTQUNBLE1BQU0sQ0FBQyxvQkFBb0IsRUFBRSxtREFBbUQsQ0FBQztTQUNqRixNQUFNLENBQUMsd0JBQXdCLEVBQUUsZ0RBQWdE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bnRlbnQiOlsiLyoqXG4gKiBgZGJ4LXRvb2xzLXR1bm5lbGAgLyBgZGJ4dC10dW5uZWxgIENMSS5cbiAqXG4gKiBXcmFwcyBhbiBhcHAncyBzdGFydCBjb21tYW5kIHdpdGggYSBwdWJsaWMgcG9ydHIgdHVubmVsIGFuZCBhbiBlbWFpbC1PVFBcbiAqIGFjY2VzcyBnYXRlLiBFdmVyeXRoaW5nIGFmdGVyIGAtLWAgaXMgdGhlIFJFQUwgYXBwIHN0YXJ0IGNvbW1hbmQ6XG4gKlxuICogICBkYnh0LXR1bm5lbCAtLXN1YmplY3QgXCJIZXJlJ3MgeW91ciBPVFBcIiAtLWFsbG93IGV4YW1wbGUuY29tIC0tIGJ1biBzcmMvc2VydmVyLnRzXG4gKlxuICogQm9vdCBzZXF1ZW5jZTpcbiAqICAgMS4gUGljayBhIHJhbmRvbSBQUklWQVRFIHBvcnQgYW5kIHNwYXduIHRoZSBhcHAgY29tbWFuZCB3aXRoXG4gKiAgICAgIGBEQVRBQlJJQ0tTX0FQUF9QT1JUYCBzZXQgdG8gaXQgKHNvIHRoZSBhcHAgYmluZHMgbG9vcGJhY2stcHJpdmF0ZSkuIFRoYXRcbiAqICAgICAgdmFyaWFibGUgbmFtZSBpcyB0aGUgRGF0YWJyaWNrcyBBcHBzIHJ1bnRpbWUgY29udHJhY3Q7IHRoZSBnYXRlIGl0c2VsZiBpc1xuICogICAgICBwbGF0Zm9ybS1uZXV0cmFsIGFuZCBob25vdXJzIHdoYXRldmVyIHBvcnQgaXQgZmluZHMgdGhlcmUuXG4gKiAgIDIuIEJvb3QgdGhlIHRpbnkgZ2F0ZSBBcHBLaXQgYXBwIChubyBzZXJ2ZXIpOiBpbml0cyBgQ2FjaGVNYW5hZ2VyYCArIHRoZVxuICogICAgICBlbWFpbCB0cmFuc3BvcnQsIHlpZWxkcyB0aGUgaW4tcHJvY2VzcyBnYXRlIEFQSS5cbiAqICAgMy4gU3RhcnQgdGhlIGdhdGUgUFJPWFkgb24gdGhlIE9SSUdJTkFMIHB1YmxpYyBwb3J0LCBmb3J3YXJkaW5nIHRvIHRoZSBhcHAuXG4gKiAgIDQuIEluc3RhbGwgKyBydW4gcG9ydHIgcG9pbnRlZCBhdCB0aGUgcHVibGljIHBvcnQgKHdoZW4gYSB0dW5uZWwgaXNcbiAqICAgICAgY29uZmlndXJlZDsgb3RoZXJ3aXNlIHRoZSBwcm94eSBzdGlsbCBnYXRlcyBub3RoaW5nIGFuZCBmb3J3YXJkcykuXG4gKlxuICogU3VwZXJ2aXNpb246IHRoZSBhcHAgY2hpbGQsIHBvcnRyIGNoaWxkLCBhbmQgdGhpcyBwcm9jZXNzIGFyZSB0aWVkIHRvZ2V0aGVyIC1cbiAqIGlmIEFOWSBleGl0cywgZXZlcnl0aGluZyBjb21lcyBkb3duIChjb25jdXJyZW50bHktc3R5bGUgYGtpbGxPdGhlcnNgKS5cbiAqXG4gKiBPcHRpb25zIGNvbWUgZnJvbSBmbGFncyBPUiBlbnY7IHNlZSB0aGUgb3B0aW9uIGRlZmluaXRpb25zIGJlbG93LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyB0eXBlIENoaWxkUHJvY2Vzcywgc3Bhd24gfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgeyBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgQ29tbWFuZCwgQ29tbWFuZGVyRXJyb3IgfSBmcm9tIFwiY29tbWFuZGVyXCI7XG5pbXBvcnQgeyBzdGFydEdhdGVBcHAgfSBmcm9tIFwiLi9hcHAudHNcIjtcbmltcG9ydCB0eXBlIHsgQXV0aEdhdGVDb25maWcgfSBmcm9tIFwiLi9wbHVnaW4udHNcIjtcbmltcG9ydCB7IGluc3RhbGxQb3J0ciwgcmVzb2x2ZVBvcnRyQ29uZmlnLCBzdGFydFBvcnRyLCB3cml0ZVBvcnRyQ29uZmlnIH0gZnJvbSBcIi4vcG9ydHIudHNcIjtcbmltcG9ydCB7IHN0YXJ0UHJveHkgfSBmcm9tIFwiLi9wcm94eS50c1wiO1xuXG5leHBvcnQgeyBDb21tYW5kZXJFcnJvciB9O1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsXCIpO1xuXG4vKiogQSByYW5kb20gZXBoZW1lcmFsIHBvcnQgZm9yIHRoZSBhcHAgdG8gYmluZCAodGhlIHByb3h5IGZyb250cyB0aGUgcHVibGljIG9uZSkuICovXG5mdW5jdGlvbiByYW5kb21Qb3J0KCk6IG51bWJlciB7XG4gIHJldHVybiAyMDAwMCArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDIwMDAwKTtcbn1cblxuaW50ZXJmYWNlIFR1bm5lbE9wdHMge1xuICBzdWJqZWN0Pzogc3RyaW5nO1xuICBhbGxvdz86IHN0cmluZztcbiAgc3ViZG9tYWluPzogc3RyaW5nO1xuICBwdWJsaWNEb21haW4/OiBzdHJpbmc7XG4gIGJyYW5kTmFtZT86IHN0cmluZztcbiAgbWVzc2FnZT86IHN0cmluZztcbiAgc2Vzc2lvblR0bD86IHN0cmluZztcbiAgY29kZVR0bD86IHN0cmluZztcbiAgaW5zZWN1cmU/OiBib29sZWFuO1xufVxuXG4vKiogQnVpbGQgdGhlIGNvbW1hbmRlciBwcm9ncmFtLiBgLS1gIHNlcGFyYXRlcyBmbGFncyBmcm9tIHRoZSBhcHAgc3RhcnQgY29tbWFuZC4gKi9cbmZ1bmN0aW9uIHByb2dyYW0oKTogQ29tbWFuZCB7XG4gIHJldHVybiBuZXcgQ29tbWFuZCgpXG4gICAgLm5hbWUoXCJkYngtdG9vbHMtdHVubmVsXCIpXG4gICAgLmRlc2NyaXB0aW9uKFwiRnJvbnQgYW4gYXBwIHdpdGggYSBwdWJsaWMgcG9ydHIgdHVubmVsICsgZW1haWwtT1RQIGdhdGVcIilcbiAgICAub3B0aW9uKFwiLS1zdWJqZWN0IDx0ZXh0PlwiLCBcIlN1YmplY3QgbGluZSBmb3IgdGhlIGNvZGUgZW1haWwgKGVudiBBVVRIX1NVQkpFQ1QpXCIpXG4gICAgLm9wdGlvbihcbiAgICAgIFwiLS1hbGxvdyA8cGF0dGVybnM+XCIsXG4gICAgICBcIkNvbW1hL3NwYWNlLXNlcGFyYXRlZCBhbGxvdy1saXN0OiBkb21haW4gLyBnbG9iIC8gL3JlZ2V4LyAoZW52IEVNQUlMX0FVVEhfQUxMT1cpXCIsXG4gICAgKVxuICAgIC5vcHRpb24oXCItLXN1YmRvbWFpbiA8bmFtZT5cIiwgXCJwb3J0ciBzdWJkb21haW4gKGVsc2UgZGVyaXZlZCBmcm9tIFBVQkxJQ19ET01BSU4pXCIpXG4gICAgLm9wdGlvbihcIi0tcHVibGljLWRvbWFpbiA8aG9zdD5cIiwgXCJwb3J0ciA8c3ViZG9tYWluPi48c2VydmVyPiAoZW52IFBVQkxJQ19ET01BSU4pXCIpXG4gICAgLm9wdGlvbihcbiAgICAgIFwiLS1icmFuZC1uYW1lIDxuYW1lPlwiLFxuICAgICAgXCJEaXNwbGF5IG5hbWUgaW4gdGhlIGNvZGUgZW1haWwgY29weSAoZW52IEFVVEhfQlJBTkRfTkFNRTsgZGVmYXVsdHMgdG8gdGhlIGJyYW5kIGNvbnRleHQgbmFtZSlcIixcbiAgICApXG4gICAgLm9wdGlvbihcIi0tbWVzc2FnZSA8dGV4dD5cIiwgXCJMaW5lIHNob3duIGFib3ZlIHRoZSBjb2RlIGluIHRoZSBlbWFpbCAoZW52IEFVVEhfTUVTU0FHRSlcIilcbiAgICAub3B0aW9uKFwiLS1zZXNzaW9uLXR0bCA8c2Vjb25kcz5cIiwgXCJTZXNzaW9uIGxpZmV0aW1lIChlbnYgQVVUSF9TRVNTSU9OX1RUTClcIilcbiAgICAub3B0aW9uKFwiLS1jb2RlLXR0bCA8c2Vjb25kcz5cIiwgXCJPbmUtdGltZS1jb2RlIGxpZmV0aW1lIChlbnYgQVVUSF9DT0RFX1RUTClcIilcbiAgICAub3B0aW9uKFxuICAgICAgXCItLWluc2VjdXJlXCIsXG4gICAgICBcIlJ1biB0aGUgdHVubmVsIE9QRU4gd2l0aCBubyBnYXRlIChlbnYgVFVOTkVMX0lOU0VDVVJFPXRydWUpLiBPdGhlcndpc2UgdGhlIENMSSBmYWlscyBmYXN0IHdoZW4gZW1haWwgU01UUCBpcyBub3QgY29uZmlndXJlZC5cIixcbiAgICApXG4gICAgLmFsbG93RXhjZXNzQXJndW1lbnRzKHRydWUpXG4gICAgLmhlbHBPcHRpb24oXCItaCwgLS1oZWxwXCIsIFwiU2hvdyBoZWxwXCIpO1xufVxuXG4vKiogVGllIGEgY2hpbGQncyBleGl0IHRvIGZ1bGwgdGVhcmRvd246IGFueSBleGl0IGJyaW5ncyB0aGUgd2hvbGUgdHVubmVsIGRvd24uICovXG5mdW5jdGlvbiBzdXBlcnZpc2VFeGl0KGNoaWxkcmVuOiBDaGlsZFByb2Nlc3NbXSk6IHZvaWQge1xuICBsZXQgc2h1dHRpbmdEb3duID0gZmFsc2U7XG4gIGNvbnN0IHNodXRkb3duID0gKGNvZGU6IG51bWJlcik6IHZvaWQgPT4ge1xuICAgIGlmIChzaHV0dGluZ0Rvd24pIHJldHVybjtcbiAgICBzaHV0dGluZ0Rvd24gPSB0cnVlO1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgY2hpbGRyZW4pIHtcbiAgICAgIGlmICghY2hpbGQua2lsbGVkKSBjaGlsZC5raWxsKFwiU0lHVEVSTVwiKTtcbiAgICB9XG4gICAgLy8gR2l2ZSBjaGlsZHJlbiBhIG1vbWVudCwgdGhlbiBleGl0IHdpdGggdGhlIGZpcnN0IG5vbi16ZXJvIGNvZGUgc2Vlbi5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHByb2Nlc3MuZXhpdChjb2RlKSwgMzAwMCkudW5yZWYoKTtcbiAgfTtcbiAgZm9yIChjb25zdCBjaGlsZCBvZiBjaGlsZHJlbikge1xuICAgIGNoaWxkLm9uKFwiZXhpdFwiLCAoY29kZSkgPT4ge1xuICAgICAgbG9nZ2VyLndhcm4oYGNoaWxkIGV4aXRlZCAoJHtjb2RlID8/IFwic2lnbmFsXCJ9KTsgYnJpbmdpbmcgdHVubmVsIGRvd25gKTtcbiAgICAgIHNodXRkb3duKGNvZGUgPz8gMSk7XG4gICAgfSk7XG4gIH1cbiAgZm9yIChjb25zdCBzaWcgb2YgW1wiU0lHVEVSTVwiLCBcIlNJR0lOVFwiLCBcIlNJR0hVUFwiXSBhcyBjb25zdCkge1xuICAgIHByb2Nlc3Mub24oc2lnLCAoKSA9PiBzaHV0ZG93bigwKSk7XG4gIH1cbn1cblxuLyoqIFBhcnNlIGFyZ3YgYW5kIHJ1biB0aGUgdHVubmVsLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJ1bkNsaShhcmd2OiBzdHJpbmdbXSk6IFByb21pc2U8dm9pZD4ge1xuICAvLyBTcGxpdCBmbGFncyBmcm9tIHRoZSB3cmFwcGVkIGNvbW1hbmQgYXQgdGhlIGZpcnN0IGAtLWAuXG4gIGNvbnN0IHNlcCA9IGFyZ3YuaW5kZXhPZihcIi0tXCIpO1xuICBjb25zdCBmbGFncyA9IHNlcCA+PSAwID8gYXJndi5zbGljZSgwLCBzZXApIDogYXJndjtcbiAgY29uc3QgY29tbWFuZCA9IHNlcCA+PSAwID8gYXJndi5zbGljZShzZXAgKyAxKSA6IFtdO1xuXG4gIGNvbnN0IHByb2cgPSBwcm9ncmFtKCk7XG4gIHByb2cucGFyc2UoZmxhZ3MpO1xuICBjb25zdCBvcHRzID0gcHJvZy5vcHRzPFR1bm5lbE9wdHM+KCk7XG5cbiAgaWYgKGNvbW1hbmQubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IENvbW1hbmRlckVycm9yKDEsIFwidHVubmVsLm5vLWNvbW1hbmRcIiwgXCJubyBzdGFydCBjb21tYW5kIGdpdmVuIGFmdGVyIGAtLWBcIik7XG4gIH1cblxuICBjb25zdCBwdWJsaWNQb3J0ID0gTnVtYmVyKHByb2Nlc3MuZW52LkRBVEFCUklDS1NfQVBQX1BPUlQgPz8gODAwMCk7XG4gIGNvbnN0IGFwcFBvcnQgPSByYW5kb21Qb3J0KCk7XG5cbiAgY29uc3QgZ2F0ZUNvbmZpZzogQXV0aEdhdGVDb25maWcgPSB7XG4gICAgYWxsb3c6IG9wdHMuYWxsb3csXG4gICAgc3ViamVjdDogb3B0cy5zdWJqZWN0LFxuICAgIGJyYW5kTmFtZTogb3B0cy5icmFuZE5hbWUsXG4gICAgbWVzc2FnZTogb3B0cy5tZXNzYWdlLFxuICAgIHNlc3Npb25UdGxTZWNvbmRzOiBvcHRzLnNlc3Npb25UdGwgPyBOdW1iZXIob3B0cy5zZXNzaW9uVHRsKSA6IHVuZGVmaW5lZCxcbiAgICBjb2RlVHRsU2Vjb25kczogb3B0cy5jb2RlVHRsID8gTnVtYmVyKG9wdHMuY29kZVR0bCkgOiB1bmRlZmluZWQsXG4gIH07XG5cbiAgLy8gMS4gU3Bhd24gdGhlIHdyYXBwZWQgYXBwIHdpdGggdGhlIFBSSVZBVEUgcG9ydC4gSXQgYmluZHMgbG9vcGJhY2s7IG9ubHkgdGhlXG4gIC8vICAgIHByb3h5IHJlYWNoZXMgaXQuXG4gIGxvZ2dlci5pbmZvKGBzcGF3bmluZyBhcHAgb24gcHJpdmF0ZSBwb3J0ICR7YXBwUG9ydH06ICR7Y29tbWFuZC5qb2luKFwiIFwiKX1gKTtcbiAgY29uc3QgW2NtZCwgLi4uYXJnc10gPSBjb21tYW5kO1xuICBjb25zdCBhcHAgPSBzcGF3bihjbWQhLCBhcmdzLCB7XG4gICAgZW52OiB7IC4uLnByb2Nlc3MuZW52LCBEQVRBQlJJQ0tTX0FQUF9QT1JUOiBTdHJpbmcoYXBwUG9ydCksIEhPU1Q6IFwiMTI3LjAuMC4xXCIgfSxcbiAgICBzdGRpbzogXCJpbmhlcml0XCIsXG4gIH0pO1xuXG4gIC8vIDIuIEJvb3QgdGhlIGdhdGUgYXBwIChjYWNoZSArIGVtYWlsIHRyYW5zcG9ydCArIGdhdGUgQVBJKS4gYHN0YXJ0R2F0ZUFwcGBcbiAgLy8gICAgRkFJTFMgRkFTVCB3aGVuIGVtYWlsIGNhbid0IHNlbmQgY29kZXMgKG5vIFNNVFApLiBJbnNlY3VyZSBtb2RlXG4gIC8vICAgIChgLS1pbnNlY3VyZWAgLyBUVU5ORUxfSU5TRUNVUkUpIHNraXBzIHRoZSBnYXRlIGFuZCBydW5zIHRoZSB0dW5uZWwgb3Blbi5cbiAgY29uc3QgaW5zZWN1cmUgPSBvcHRzLmluc2VjdXJlIHx8IC9eKDF8dHJ1ZXx5ZXN8b24pJC9pLnRlc3QocHJvY2Vzcy5lbnYuVFVOTkVMX0lOU0VDVVJFID8/IFwiXCIpO1xuICBsZXQgZ2F0ZTogQXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiBzdGFydEdhdGVBcHA+PiB8IHVuZGVmaW5lZDtcbiAgaWYgKGluc2VjdXJlKSB7XG4gICAgbG9nZ2VyLndhcm4oXCJpbnNlY3VyZSBtb2RlIC0gdHVubmVsIHJ1bnMgT1BFTiB3aXRoIG5vIGVtYWlsLU9UUCBnYXRlXCIpO1xuICB9IGVsc2Uge1xuICAgIHRyeSB7XG4gICAgICBnYXRlID0gYXdhaXQgc3RhcnRHYXRlQXBwKGdhdGVDb25maWcpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBGYWlsIGZhc3Q6IGRvbid0IHNpbGVudGx5IGV4cG9zZSBhbiB1bmdhdGVkIHR1bm5lbC4gVGhlIG9wZXJhdG9yIG11c3QgZml4XG4gICAgICAvLyBTTVRQIG9yIGV4cGxpY2l0bHkgb3B0IGludG8gYC0taW5zZWN1cmVgLlxuICAgICAgbG9nZ2VyLmVycm9yKFwiY2Fubm90IHN0YXJ0IHRoZSBPVFAgZ2F0ZVwiLCB7IGVycm9yOiAoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2UgfSk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICAvLyAzLiBTdGFydCB0aGUgZ2F0ZSBwcm94eSBvbiB0aGUgcHVibGljIHBvcnQgKG9wZW4gd2hlbiBgZ2F0ZWAgaXMgdW5kZWZpbmVkKS5cbiAgYXdhaXQgc3RhcnRQcm94eSh7IHB1YmxpY1BvcnQsIGFwcFBvcnQsIGdhdGUgfSk7XG5cbiAgLy8gNC4gSW5zdGFsbCArIHJ1biBwb3J0ciB3aGVuIGEgdHVubmVsIGlzIGNvbmZpZ3VyZWQuXG4gIGNvbnN0IHBvcnRyQ29uZmlnID0gcmVzb2x2ZVBvcnRyQ29uZmlnKHtcbiAgICBwdWJsaWNEb21haW46IG9wdHMucHVibGljRG9tYWluLFxuICAgIHN1YmRvbWFpbjogb3B0cy5zdWJkb21haW4sXG4gICAgcG9ydDogcHVibGljUG9ydCxcbiAgfSk7XG4gIGNvbnN0IGNoaWxkcmVuOiBDaGlsZFByb2Nlc3NbXSA9IFthcHBdO1xuICBpZiAocG9ydHJDb25maWcpIHtcbiAgICBjb25zdCBlbnYgPSBpbnN0YWxsUG9ydHIoKTtcbiAgICB3cml0ZVBvcnRyQ29uZmlnKHBvcnRyQ29uZmlnLCBlbnYpO1xuICAgIGNoaWxkcmVuLnB1c2goc3RhcnRQb3J0cihwb3J0ckNvbmZpZywgZW52KSk7XG4gIH0gZWxzZSB7XG4gICAgbG9nZ2VyLmluZm8oXCJubyBQT1JUUl9UT0tFTi9QVUJMSUNfRE9NQUlOIC0gc2VydmluZyB0aGUgZ2F0ZSBwcm94eSB3aXRob3V0IGEgcHVibGljIHR1bm5lbFwiKTtcbiAgfVxuXG4gIC8vIEFueSBjaGlsZCBleGl0IChvciBhIHNpZ25hbCkgdGVhcnMgdGhlIHdob2xlIHRoaW5nIGRvd24uXG4gIHN1cGVydmlzZUV4aXQoY2hpbGRyZW4pO1xufVxuIl19
157
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlCRztBQUVILE9BQU8sRUFBcUIsS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDOUQsT0FBTyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxZQUFZLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFN0QsT0FBTyxFQUFFLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDNUYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV4QyxPQUFPLEVBQUUsY0FBYyxFQUFFLENBQUM7QUFFMUIsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUVwQyxxRkFBcUY7QUFDckYsU0FBUyxVQUFVO0lBQ2pCLE9BQU8sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFlRCxvRkFBb0Y7QUFDcEYsU0FBUyxPQUFPO0lBQ2QsT0FBTyxJQUFJLE9BQU8sRUFBRTtTQUNqQixJQUFJLENBQUMsa0JBQWtCLENBQUM7U0FDeEIsV0FBVyxDQUFDLDBEQUEwRCxDQUFDO1NBQ3ZFLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSwyREFBMkQsQ0FBQztTQUN2RixNQUFNLENBQ0wsb0JBQW9CLEVBQ3BCLG1GQUFtRixDQUNwRjtTQUNBLE1BQU0s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QUUsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUNuRCxDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sQ0FBQyxJQUFJLENBQ1Qsc0ZBQXNGLENBQ3ZGLENBQUM7SUFDSixDQUFDO0lBRUQsMkRBQTJEO0lBQzNELGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUMxQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBgZGJ4LXRvb2xzLXR1bm5lbGAgLyBgZGJ4dC10dW5uZWxgIENMSS5cbiAqXG4gKiBXcmFwcyBhbiBhcHAncyBzdGFydCBjb21tYW5kIHdpdGggYSBwdWJsaWMgcG9ydHIgdHVubmVsIGFuZCBhbiBlbWFpbC1PVFBcbiAqIGFjY2VzcyBnYXRlLiBFdmVyeXRoaW5nIGFmdGVyIGAtLWAgaXMgdGhlIFJFQUwgYXBwIHN0YXJ0IGNvbW1hbmQ6XG4gKlxuICogICBkYnh0LXR1bm5lbCAtLXN1YmplY3QgXCJIZXJlJ3MgeW91ciBPVFBcIiAtLWFsbG93IGV4YW1wbGUuY29tIC0tIGJ1biBzcmMvc2VydmVyLnRzXG4gKlxuICogQm9vdCBzZXF1ZW5jZTpcbiAqICAgMS4gUGljayBhIHJhbmRvbSBQUklWQVRFIHBvcnQgYW5kIHNwYXduIHRoZSBhcHAgY29tbWFuZCB3aXRoXG4gKiAgICAgIGBEQVRBQlJJQ0tTX0FQUF9QT1JUYCBzZXQgdG8gaXQgKHNvIHRoZSBhcHAgYmluZHMgbG9vcGJhY2stcHJpdmF0ZSkuIFRoYXRcbiAqICAgICAgdmFyaWFibGUgbmFtZSBpcyB0aGUgRGF0YWJyaWNrcyBBcHBzIHJ1bnRpbWUgY29udHJhY3Q7IHRoZSBnYXRlIGl0c2VsZiBpc1xuICogICAgICBwbGF0Zm9ybS1uZXV0cmFsIGFuZCBob25vdXJzIHdoYXRldmVyIHBvcnQgaXQgZmluZHMgdGhlcmUuXG4gKiAgIDIuIEJvb3QgdGhlIHRpbnkgZ2F0ZSBBcHBLaXQgYXBwIChubyBzZXJ2ZXIpOiBpbml0cyBgQ2FjaGVNYW5hZ2VyYCArIHRoZVxuICogICAgICBlbWFpbCB0cmFuc3BvcnQsIHlpZWxkcyB0aGUgaW4tcHJvY2VzcyBnYXRlIEFQSS5cbiAqICAgMy4gU3RhcnQgdGhlIGdhdGUgUFJPWFkgb24gdGhlIE9SSUdJTkFMIHB1YmxpYyBwb3J0LCBmb3J3YXJkaW5nIHRvIHRoZSBhcHAuXG4gKiAgIDQuIEluc3RhbGwgKyBydW4gcG9ydHIgcG9pbnRlZCBhdCB0aGUgcHVibGljIHBvcnQgKHdoZW4gYSB0dW5uZWwgaXNcbiAqICAgICAgY29uZmlndXJlZDsgb3RoZXJ3aXNlIHRoZSBwcm94eSBzdGlsbCBnYXRlcyBub3RoaW5nIGFuZCBmb3J3YXJkcykuXG4gKlxuICogU3VwZXJ2aXNpb246IHRoZSBhcHAgY2hpbGQsIHBvcnRyIGNoaWxkLCBhbmQgdGhpcyBwcm9jZXNzIGFyZSB0aWVkIHRvZ2V0aGVyIC1cbiAqIGlmIEFOWSBleGl0cywgZXZlcnl0aGluZyBjb21lcyBkb3duIChjb25jdXJyZW50bHktc3R5bGUgYGtpbGxPdGhlcnNgKS5cbiAqXG4gKiBPcHRpb25zIGNvbWUgZnJvbSBmbGFncyBPUiBlbnY7IHNlZSB0aGUgb3B0aW9uIGRlZmluaXRpb25zIGJlbG93LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyB0eXBlIENoaWxkUHJvY2Vzcywgc3Bhd24gfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgeyBlbnYsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBDb21tYW5kLCBDb21tYW5kZXJFcnJvciB9IGZyb20gXCJjb21tYW5kZXJcIjtcbmltcG9ydCB7IHN0YXJ0R2F0ZUFwcCB9IGZyb20gXCIuL2FwcC50c1wiO1xuaW1wb3J0IHsgRk9SV0FSRF9IRUFERVJTX0VOViwgSU5TRUNVUkVfRU5WIH0gZnJvbSBcIi4vZW52LnRzXCI7XG5pbXBvcnQgdHlwZSB7IEF1dGhHYXRlQ29uZmlnIH0gZnJvbSBcIi4vcGx1Z2luLnRzXCI7XG5pbXBvcnQgeyBpbnN0YWxsUG9ydHIsIHJlc29sdmVQb3J0ckNvbmZpZywgc3RhcnRQb3J0ciwgd3JpdGVQb3J0ckNvbmZpZyB9IGZyb20gXCIuL3BvcnRyLnRzXCI7XG5pbXBvcnQgeyBzdGFydFByb3h5IH0gZnJvbSBcIi4vcHJveHkudHNcIjtcblxuZXhwb3J0IHsgQ29tbWFuZGVyRXJyb3IgfTtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcInR1bm5lbFwiKTtcblxuLyoqIEEgcmFuZG9tIGVwaGVtZXJhbCBwb3J0IGZvciB0aGUgYXBwIHRvIGJpbmQgKHRoZSBwcm94eSBmcm9udHMgdGhlIHB1YmxpYyBvbmUpLiAqL1xuZnVuY3Rpb24gcmFuZG9tUG9ydCgpOiBudW1iZXIge1xuICByZXR1cm4gMjAwMDAgKyBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAyMDAwMCk7XG59XG5cbmludGVyZmFjZSBUdW5uZWxPcHRzIHtcbiAgc3ViamVjdD86IHN0cmluZztcbiAgYWxsb3c/OiBzdHJpbmc7XG4gIHN1YmRvbWFpbj86IHN0cmluZztcbiAgcHVibGljRG9tYWluPzogc3RyaW5nO1xuICBicmFuZE5hbWU/OiBzdHJpbmc7XG4gIG1lc3NhZ2U/OiBzdHJpbmc7XG4gIHNlc3Npb25UdGw/OiBzdHJpbmc7XG4gIGNvZGVUdGw/OiBzdHJpbmc7XG4gIGluc2VjdXJlPzogYm9vbGVhbjtcbiAgZm9yd2FyZEhlYWRlcnM/OiBzdHJpbmc7XG59XG5cbi8qKiBCdWlsZCB0aGUgY29tbWFuZGVyIHByb2dyYW0uIGAtLWAgc2VwYXJhdGVzIGZsYWdzIGZyb20gdGhlIGFwcCBzdGFydCBjb21tYW5kLiAqL1xuZnVuY3Rpb24gcHJvZ3JhbSgpOiBDb21tYW5kIHtcbiAgcmV0dXJuIG5ldyBDb21tYW5kKClcbiAgICAubmFtZShcImRieC10b29scy10dW5uZWxcIilcbiAgICAuZGVzY3JpcHRpb24oXCJGcm9udCBhbiBhcHAgd2l0aCBhIHB1YmxpYyBwb3J0ciB0dW5uZWwgKyBlbWFpbC1PVFAgZ2F0ZVwiKVxuICAgIC5vcHRpb24oXCItLXN1YmplY3QgPHRleHQ+XCIsIFwiU3ViamVjdCBsaW5lIGZvciB0aGUgY29kZSBlbWFpbCAoZW52IFRVTk5FTF9BVVRIX1NVQkpFQ1QpXCIpXG4gICAgLm9wdGlvbihcbiAgICAgIFwiLS1hbGxvdyA8cGF0dGVybnM+XCIsXG4gICAgICBcIkNvbW1hL3NwYWNlLXNlcGFyYXRlZCBhbGxvdy1saXN0OiBkb21haW4gLyBnbG9iIC8gL3JlZ2V4LyAoZW52IFRVTk5FTF9BVVRIX0FMTE9XKVwiLFxuICAgIClcbiAgICAub3B0aW9uKFwiLS1zdWJkb21haW4gPG5hbWU+XCIsIFwicG9ydHIgc3ViZG9tYWluIChlbHNlIGRlcml2ZWQgZnJvbSBUVU5ORUxfUFVCTElDX0RPTUFJTilcIilcbiAgICAub3B0aW9uKFwiLS1wdWJsaWMtZG9tYWluIDxob3N0PlwiLCBcInBvcnRyIDxzdWJkb21haW4+LjxzZXJ2ZXI+IChlbnYgVFVOTkVMX1BVQkxJQ19ET01BSU4pXCIpXG4gICAgLm9wdGlvbihcbiAgICAgIFwiLS1icmFuZC1uYW1lIDxuYW1lPlwiLFxuICAgICAgXCJEaXNwbGF5IG5hbWUgaW4gdGhlIGNvZGUgZW1haWwgY29weSAoZW52IFRVTk5FTF9BVVRIX0JSQU5EX05BTUU7IGRlZmF1bHRzIHRvIHRoZSBicmFuZCBjb250ZXh0IG5hbWUpXCIsXG4gICAgKVxuICAgIC5vcHRpb24oXCItLW1lc3NhZ2UgPHRleHQ+XCIsIFwiTGluZSBzaG93biBhYm92ZSB0aGUgY29kZSBpbiB0aGUgZW1haWwgKGVudiBUVU5ORUxfQVVUSF9NRVNTQUdFKVwiKVxuICAgIC5vcHRpb24oXCItLXNlc3Npb24tdHRsIDxzZWNvbmRzPlwiLCBcIlNlc3Npb24gbGlmZXRpbWUgKGVudiBUVU5ORUxfQVVUSF9TRVNTSU9OX1RUTClcIilcbiAgICAub3B0aW9uKFwiLS1jb2RlLXR0bCA8c2Vjb25kcz5cIiwgXCJPbmUtdGltZS1jb2RlIGxpZmV0aW1lIChlbnYgVFVOTkVMX0FVVEhfQ09ERV9UVEwpXCIpXG4gICAgLm9wdGlvbihcbiAgICAgIFwiLS1mb3J3YXJkLWhlYWRlcnMgPHBhdHRlcm5zPlwiLFxuICAgICAgXCJFeHRyYSB4LSByZXF1ZXN0IGhlYWRlcnMgdHVubmVsIHRyYWZmaWMgbWF5IGZvcndhcmQ6IGxpdGVyYWwgLyBnbG9iIC8gL3JlZ2V4LyAoZW52IFRVTk5FTF9GT1JXQVJEX0hFQURFUlMpXCIsXG4gICAgKVxuICAgIC5vcHRpb24oXG4gICAgICBcIi0taW5zZWN1cmVcIixcbiAgICAgIFwiUnVuIHRoZSB0dW5uZWwgT1BFTiB3aXRoIG5vIGdhdGUgKGVudiBUVU5ORUxfSU5TRUNVUkU9dHJ1ZSkuIE90aGVyd2lzZSB0aGUgQ0xJIGZhaWxzIGZhc3Qgd2hlbiBlbWFpbCBTTVRQIGlzIG5vdCBjb25maWd1cmVkLlwiLFxuICAgIClcbiAgICAuYWxsb3dFeGNlc3NBcmd1bWVudHModHJ1ZSlcbiAgICAuaGVscE9wdGlvbihcIi1oLCAtLWhlbHBcIiwgXCJTaG93IGhlbHBcIik7XG59XG5cbi8qKiBUaWUgYSBjaGlsZCdzIGV4aXQgdG8gZnVsbCB0ZWFyZG93bjogYW55IGV4aXQgYnJpbmdzIHRoZSB3aG9sZSB0dW5uZWwgZG93bi4gKi9cbmZ1bmN0aW9uIHN1cGVydmlzZUV4aXQoY2hpbGRyZW46IENoaWxkUHJvY2Vzc1tdKTogdm9pZCB7XG4gIGxldCBzaHV0dGluZ0Rvd24gPSBmYWxzZTtcbiAgY29uc3Qgc2h1dGRvd24gPSAoY29kZTogbnVtYmVyKTogdm9pZCA9PiB7XG4gICAgaWYgKHNodXR0aW5nRG93bikgcmV0dXJuO1xuICAgIHNodXR0aW5nRG93biA9IHRydWU7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBjaGlsZHJlbikge1xuICAgICAgaWYgKCFjaGlsZC5raWxsZWQpIGNoaWxkLmtpbGwoXCJTSUdURVJNXCIpO1xuICAgIH1cbiAgICAvLyBHaXZlIGNoaWxkcmVuIGEgbW9tZW50LCB0aGVuIGV4aXQgd2l0aCB0aGUgZmlyc3Qgbm9uLXplcm8gY29kZSBzZWVuLlxuICAgIHNldFRpbWVvdXQoKCkgPT4gcHJvY2Vzcy5leGl0KGNvZGUpLCAzMDAwKS51bnJlZigpO1xuICB9O1xuICBmb3IgKGNvbnN0IGNoaWxkIG9mIGNoaWxkcmVuKSB7XG4gICAgY2hpbGQub24oXCJleGl0XCIsIChjb2RlKSA9PiB7XG4gICAgICBsb2dnZXIud2FybihgY2hpbGQgZXhpdGVkICgke2NvZGUgPz8gXCJzaWduYWxcIn0pOyBicmluZ2luZyB0dW5uZWwgZG93bmApO1xuICAgICAgc2h1dGRvd24oY29kZSA/PyAxKTtcbiAgICB9KTtcbiAgfVxuICBmb3IgKGNvbnN0IHNpZyBvZiBbXCJTSUdURVJNXCIsIFwiU0lHSU5UXCIsIFwiU0lHSFVQXCJdIGFzIGNvbnN0KSB7XG4gICAgcHJvY2Vzcy5vbihzaWcsICgpID0+IHNodXRkb3duKDApKTtcbiAgfVxufVxuXG4vKiogUGFyc2UgYXJndiBhbmQgcnVuIHRoZSB0dW5uZWwuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuQ2xpKGFyZ3Y6IHN0cmluZ1tdKTogUHJvbWlzZTx2b2lkPiB7XG4gIC8vIFNwbGl0IGZsYWdzIGZyb20gdGhlIHdyYXBwZWQgY29tbWFuZCBhdCB0aGUgZmlyc3QgYC0tYC5cbiAgY29uc3Qgc2VwID0gYXJndi5pbmRleE9mKFwiLS1cIik7XG4gIGNvbnN0IGZsYWdzID0gc2VwID49IDAgPyBhcmd2LnNsaWNlKDAsIHNlcCkgOiBhcmd2O1xuICBjb25zdCBjb21tYW5kID0gc2VwID49IDAgPyBhcmd2LnNsaWNlKHNlcCArIDEpIDogW107XG5cbiAgY29uc3QgcHJvZyA9IHByb2dyYW0oKTtcbiAgcHJvZy5wYXJzZShmbGFncyk7XG4gIGNvbnN0IG9wdHMgPSBwcm9nLm9wdHM8VHVubmVsT3B0cz4oKTtcblxuICBpZiAoY29tbWFuZC5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgQ29tbWFuZGVyRXJyb3IoMSwgXCJ0dW5uZWwubm8tY29tbWFuZFwiLCBcIm5vIHN0YXJ0IGNvbW1hbmQgZ2l2ZW4gYWZ0ZXIgYC0tYFwiKTtcbiAgfVxuXG4gIGNvbnN0IHB1YmxpY1BvcnQgPSBOdW1iZXIocHJvY2Vzcy5lbnYuREFUQUJSSUNLU19BUFBfUE9SVCA/PyA4MDAwKTtcbiAgY29uc3QgYXBwUG9ydCA9IHJhbmRvbVBvcnQoKTtcblxuICBjb25zdCBnYXRlQ29uZmlnOiBBdXRoR2F0ZUNvbmZpZyA9IHtcbiAgICBhbGxvdzogb3B0cy5hbGxvdyxcbiAgICBzdWJqZWN0OiBvcHRzLnN1YmplY3QsXG4gICAgYnJhbmROYW1lOiBvcHRzLmJyYW5kTmFtZSxcbiAgICBtZXNzYWdlOiBvcHRzLm1lc3NhZ2UsXG4gICAgc2Vzc2lvblR0bFNlY29uZHM6IG9wdHMuc2Vzc2lvblR0bCA/IE51bWJlcihvcHRzLnNlc3Npb25UdGwpIDogdW5kZWZpbmVkLFxuICAgIGNvZGVUdGxTZWNvbmRzOiBvcHRzLmNvZGVUdGwgPyBOdW1iZXIob3B0cy5jb2RlVHRsKSA6IHVuZGVmaW5lZCxcbiAgfTtcblxuICAvLyAxLiBTcGF3biB0aGUgd3JhcHBlZCBhcHAgd2l0aCB0aGUgUFJJVkFURSBwb3J0LiBJdCBiaW5kcyBsb29wYmFjazsgb25seSB0aGVcbiAgLy8gICAgcHJveHkgcmVhY2hlcyBpdC5cbiAgbG9nZ2VyLmluZm8oYHNwYXduaW5nIGFwcCBvbiBwcml2YXRlIHBvcnQgJHthcHBQb3J0fTogJHtjb21tYW5kLmpvaW4oXCIgXCIpfWApO1xuICBjb25zdCBbY21kLCAuLi5hcmdzXSA9IGNvbW1hbmQ7XG4gIGNvbnN0IGFwcCA9IHNwYXduKGNtZCEsIGFyZ3MsIHtcbiAgICBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIERBVEFCUklDS1NfQVBQX1BPUlQ6IFN0cmluZyhhcHBQb3J0KSwgSE9TVDogXCIxMjcuMC4wLjFcIiB9LFxuICAgIHN0ZGlvOiBcImluaGVyaXRcIixcbiAgfSk7XG5cbiAgLy8gMi4gQm9vdCB0aGUgZ2F0ZSBhcHAgKGNhY2hlICsgZW1haWwgdHJhbnNwb3J0ICsgZ2F0ZSBBUEkpLiBgc3RhcnRHYXRlQXBwYFxuICAvLyAgICBGQUlMUyBGQVNUIHdoZW4gZW1haWwgY2FuJ3Qgc2VuZCBjb2RlcyAobm8gU01UUCkuIEluc2VjdXJlIG1vZGVcbiAgLy8gICAgKGAtLWluc2VjdXJlYCAvIFRVTk5FTF9JTlNFQ1VSRSkgc2tpcHMgdGhlIGdhdGUgYW5kIHJ1bnMgdGhlIHR1bm5lbCBvcGVuLlxuICBjb25zdCBpbnNlY3VyZSA9IGVudi5ib29sZWFuKG9wdHMuaW5zZWN1cmUsIElOU0VDVVJFX0VOVikgPz8gZmFsc2U7XG4gIGxldCBnYXRlOiBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIHN0YXJ0R2F0ZUFwcD4+IHwgdW5kZWZpbmVkO1xuICBpZiAoaW5zZWN1cmUpIHtcbiAgICBsb2dnZXIud2FybihcImluc2VjdXJlIG1vZGUgLSB0dW5uZWwgcnVucyBPUEVOIHdpdGggbm8gZW1haWwtT1RQIGdhdGVcIik7XG4gIH0gZWxzZSB7XG4gICAgdHJ5IHtcbiAgICAgIGdhdGUgPSBhd2FpdCBzdGFydEdhdGVBcHAoZ2F0ZUNvbmZpZyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIEZhaWwgZmFzdDogZG9uJ3Qgc2lsZW50bHkgZXhwb3NlIGFuIHVuZ2F0ZWQgdHVubmVsLiBUaGUgb3BlcmF0b3IgbXVzdCBmaXhcbiAgICAgIC8vIFNNVFAgb3IgZXhwbGljaXRseSBvcHQgaW50byBgLS1pbnNlY3VyZWAuXG4gICAgICBsb2dnZXIuZXJyb3IoXCJjYW5ub3Qgc3RhcnQgdGhlIE9UUCBnYXRlXCIsIHsgZXJyb3I6IChlcnJvciBhcyBFcnJvcikubWVzc2FnZSB9KTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuXG4gIC8vIDMuIFN0YXJ0IHRoZSBnYXRlIHByb3h5IG9uIHRoZSBwdWJsaWMgcG9ydCAob3BlbiB3aGVuIGBnYXRlYCBpcyB1bmRlZmluZWQpLlxuICAvLyAgICBgZm9yd2FyZEhlYWRlcnNgIG9ubHkgQUREUyB0byB0aGUgYnVpbHQtaW4gYWxsb3ctbGlzdDsgc2VlIGAuL2hlYWRlcnMudHNgLlxuICBhd2FpdCBzdGFydFByb3h5KHtcbiAgICBwdWJsaWNQb3J0LFxuICAgIGFwcFBvcnQsXG4gICAgZ2F0ZSxcbiAgICBmb3J3YXJkSGVhZGVyczogZW52Lmxpc3Qob3B0cy5mb3J3YXJkSGVhZGVycywgRk9SV0FSRF9IRUFERVJTX0VOViksXG4gIH0pO1xuXG4gIC8vIDQuIEluc3RhbGwgKyBydW4gcG9ydHIgd2hlbiBhIHR1bm5lbCBpcyBjb25maWd1cmVkLlxuICBjb25zdCBwb3J0ckNvbmZpZyA9IHJlc29sdmVQb3J0ckNvbmZpZyh7XG4gICAgcHVibGljRG9tYWluOiBvcHRzLnB1YmxpY0RvbWFpbixcbiAgICBzdWJkb21haW46IG9wdHMuc3ViZG9tYWluLFxuICAgIHBvcnQ6IHB1YmxpY1BvcnQsXG4gIH0pO1xuICBjb25zdCBjaGlsZHJlbjogQ2hpbGRQcm9jZXNzW10gPSBbYXBwXTtcbiAgaWYgKHBvcnRyQ29uZmlnKSB7XG4gICAgY29uc3QgcG9ydHJFbnYgPSBpbnN0YWxsUG9ydHIoKTtcbiAgICB3cml0ZVBvcnRyQ29uZmlnKHBvcnRyQ29uZmlnLCBwb3J0ckVudik7XG4gICAgY2hpbGRyZW4ucHVzaChzdGFydFBvcnRyKHBvcnRyQ29uZmlnLCBwb3J0ckVudikpO1xuICB9IGVsc2Uge1xuICAgIGxvZ2dlci5pbmZvKFxuICAgICAgXCJubyBQT1JUUl9UT0tFTi9UVU5ORUxfUFVCTElDX0RPTUFJTiAtIHNlcnZpbmcgdGhlIGdhdGUgcHJveHkgd2l0aG91dCBhIHB1YmxpYyB0dW5uZWxcIixcbiAgICApO1xuICB9XG5cbiAgLy8gQW55IGNoaWxkIGV4aXQgKG9yIGEgc2lnbmFsKSB0ZWFycyB0aGUgd2hvbGUgdGhpbmcgZG93bi5cbiAgc3VwZXJ2aXNlRXhpdChjaGlsZHJlbik7XG59XG4iXX0=
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Environment-variable names the tunnel reads.
3
+ *
4
+ * Every setting is `TUNNEL_`-prefixed, matching the repo convention of naming a
5
+ * variable after the package that owns it (`MASTRA_*`, `TEAMS_*`,
6
+ * `WEB_SEARCH_*`). The gate's original names were unprefixed (`AUTH_SUBJECT`,
7
+ * `PUBLIC_DOMAIN`, ...), which is a real hazard for a package that runs as a
8
+ * WRAPPER: the tunnel and the app it wraps share one environment, so a generic
9
+ * name is one the wrapped app may already use for something else, and
10
+ * `PUBLIC_DOMAIN` in particular reads like an app-wide setting rather than a
11
+ * portr detail. `EMAIL_AUTH_ALLOW` was worse than generic - it sat in
12
+ * `@dbx-tools/email`'s `EMAIL_*` namespace while configuring the gate, not email.
13
+ *
14
+ * Each entry is an {@link EnvKey} list, EARLIEST-WINS, whose first element is the
15
+ * current name and whose remaining elements are the deprecated originals. A
16
+ * deployment set up against the old names keeps working; nothing needs a
17
+ * coordinated rename. Read them through `env.string` / `env.positiveInt` /
18
+ * `env.list`, which accept the list directly.
19
+ *
20
+ * Not renamed:
21
+ *
22
+ * - `DATABRICKS_APP_PORT` - the Databricks Apps runtime contract. The platform
23
+ * sets it; the gate honours it.
24
+ * - `PORTR_TOKEN` / `PORTR_SERVER` / `PORTR_AUTO_ADD_PATH` - upstream
25
+ * [portr](https://github.com/amalshaji/portr)'s own namespace, and
26
+ * `PORTR_AUTO_ADD_PATH` is passed straight to that binary. Renaming these
27
+ * would rename someone else's contract.
28
+ *
29
+ * @module
30
+ */
31
+ import type { EnvKey } from "@dbx-tools/shared-core";
32
+ /** Access allow-list patterns (domain / glob / `/regex/`). */
33
+ export declare const ALLOW_ENV: EnvKey;
34
+ /** Subject line for the code email. */
35
+ export declare const SUBJECT_ENV: EnvKey;
36
+ /** Display name used in the code email copy. */
37
+ export declare const BRAND_NAME_ENV: EnvKey;
38
+ /** Line shown immediately above the code in the email. */
39
+ export declare const MESSAGE_ENV: EnvKey;
40
+ /** Session lifetime, in seconds. */
41
+ export declare const SESSION_TTL_ENV: EnvKey;
42
+ /** One-time-code lifetime, in seconds. */
43
+ export declare const CODE_TTL_ENV: EnvKey;
44
+ /** HS256 signing secret for the session JWT. */
45
+ export declare const JWT_SECRET_ENV: EnvKey;
46
+ /** The public `<subdomain>.<server>` portr should serve on. */
47
+ export declare const PUBLIC_DOMAIN_ENV: EnvKey;
48
+ /** Run the tunnel OPEN, with no gate. Ignored unless truthy. */
49
+ export declare const INSECURE_ENV: EnvKey;
50
+ /** Extra `x-` request headers tunnel traffic may forward. */
51
+ export declare const FORWARD_HEADERS_ENV: EnvKey;