@dbx-tools/cli 0.9.131 → 0.9.136

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.
@@ -45,6 +45,9 @@ export const TunnelOptionsSchema = z
45
45
  allow: list("Email allow-list patterns.").meta({ env: "TUNNEL_AUTH_ALLOW" }),
46
46
  subject: text("Verification email subject.").meta({ env: "TUNNEL_AUTH_SUBJECT" }),
47
47
  brandName: text("Verification email brand name.").meta({ env: "TUNNEL_AUTH_BRAND_NAME" }),
48
+ passkeyNamePrefix: text("Prefix for humanized tunnel passkey names.").meta({
49
+ env: "TUNNEL_AUTH_PASSKEY_NAME_PREFIX",
50
+ }),
48
51
  message: text("Verification email message.").meta({ env: "TUNNEL_AUTH_MESSAGE" }),
49
52
  sessionTtlSeconds: z.coerce
50
53
  .number<number>()
@@ -127,6 +130,7 @@ export function resolveTunnelOptions(options: TunnelOptions): ResolvedTunnelOpti
127
130
  allow: options.allow,
128
131
  subject: options.subject,
129
132
  brandName: options.brandName,
133
+ passkeyNamePrefix: options.passkeyNamePrefix,
130
134
  message: options.message,
131
135
  // Coerced, not resolved: the plugin owns the env name and the default for
132
136
  // these, so the flag is passed through as the `config` value it expects and
@@ -46,6 +46,8 @@ export interface ProxyOptions {
46
46
  gatePaths?: readonly string[];
47
47
  /** Brand name for the hosted login page shown on a denied browser navigation. */
48
48
  brandName?: string;
49
+ /** Prefix added before the humanized tunnel subdomain in new passkey names. */
50
+ passkeyNamePrefix?: string;
49
51
  /**
50
52
  * Addresses to listen on. Defaults to a single `0.0.0.0` (every interface),
51
53
  * the portr/platform case. Pass specific interface IPs to expose the gate on
@@ -77,6 +79,7 @@ async function handleAuthRoute(
77
79
  path: string,
78
80
  gate: AuthGateApi,
79
81
  brandName: string,
82
+ passkeyNamePrefix?: string,
80
83
  ): Promise<boolean> {
81
84
  if (!tunnelGate.isAuthPath(path)) return false;
82
85
  if (tunnelGate.wantsHostedLogin(request)) {
@@ -84,6 +87,7 @@ async function handleAuthRoute(
84
87
  response.end(
85
88
  tunnelLoginPage.loginPageHtml({
86
89
  brandName,
90
+ passkeyNamePrefix,
87
91
  returnTo: tunnelGate.loginReturnTo(request),
88
92
  }),
89
93
  );
@@ -126,13 +130,20 @@ export async function startProxy(options: ProxyOptions): Promise<void> {
126
130
  void (async () => {
127
131
  const path = (request.url ?? "/").split("?")[0] ?? "/";
128
132
  const brandName = options.brandName ?? "this app";
129
- if (gate && (await handleAuthRoute(request, response, path, gate, brandName))) return;
133
+ const passkeyNamePrefix = options.passkeyNamePrefix;
134
+ if (
135
+ gate &&
136
+ (await handleAuthRoute(request, response, path, gate, brandName, passkeyNamePrefix))
137
+ ) {
138
+ return;
139
+ }
130
140
  if ((await decide(request)) === "deny") {
131
141
  // A denied browser navigation gets the hosted login page; anything else
132
142
  // (an XHR, a /ws upgrade probe, a non-HTML fetch) gets the 401 JSON.
133
143
  if (gate && tunnelGate.wantsLoginPage(request)) {
134
144
  const html = tunnelLoginPage.loginPageHtml({
135
145
  brandName,
146
+ passkeyNamePrefix,
136
147
  returnTo: tunnelGate.requestReturnTo(request),
137
148
  });
138
149
  response.writeHead(401, { "content-type": "text/html; charset=utf-8" });