@dbx-tools/cli-tunnel 0.6.54 → 0.6.55
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 +13 -1
- package/lib/src/app.d.ts +33 -3
- package/lib/src/app.js +56 -24
- package/package.json +6 -6
- package/src/app.ts +63 -23
package/README.md
CHANGED
|
@@ -29,7 +29,19 @@ address against an allow-list, verified by a code sent over
|
|
|
29
29
|
code input carries `autocomplete="one-time-code"`. iOS, Gmail, Outlook, and
|
|
30
30
|
Android detect a code from that shape and offer it directly from the
|
|
31
31
|
notification; novel phrasing is what breaks the detection. Both MIME parts carry
|
|
32
|
-
the code as visible text, never an image.
|
|
32
|
+
the code as visible text, never an image, and no trailer follows the copy.
|
|
33
|
+
- The two MIME parts are built separately, on purpose. The HTML part is the full
|
|
34
|
+
branded template with the code as a large styled heading; the `text/plain` part
|
|
35
|
+
is authored directly, keeping the prompt and the code on ONE line
|
|
36
|
+
(`Your verification code is: 123456`) because that is the shape client code
|
|
37
|
+
detection reads most reliably. A generated text part cannot hold it - the text
|
|
38
|
+
part is a rendering of the HTML, so the heading's CSS margin arrives as blank
|
|
39
|
+
lines and autofill stops being offered while the HTML still looks perfect. See
|
|
40
|
+
`codeEmailTextBody` in the `app` module.
|
|
41
|
+
- The sign-in code is SYSTEM mail: it sends from `no-reply@EMAIL_DOMAIN` (or
|
|
42
|
+
`EMAIL_SYSTEM_FROM`), never a person's address, since a reply to a
|
|
43
|
+
machine-generated code reaches nobody. `EMAIL_FROM` is not required - see
|
|
44
|
+
[`@dbx-tools/email`](../../node/email#sender-addresses).
|
|
33
45
|
- Email one-time-code gate: a 6-digit code stored as a SHA-256 hash with an
|
|
34
46
|
attempt counter, verified in constant time, in AppKit's `CacheManager` (memory
|
|
35
47
|
by default, Lakebase when the app configures persistent `CacheStorage`) so TTL
|
package/lib/src/app.d.ts
CHANGED
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
*
|
|
12
12
|
* It returns the {@link AuthGateApi} the proxy drives. `sendCode` is wired here
|
|
13
13
|
* (the plugin can't resolve HOW to send on its own) to the email plugin's
|
|
14
|
-
* transport
|
|
15
|
-
*
|
|
14
|
+
* transport. A sign-in code is SYSTEM mail - no on-behalf-of user asked for it
|
|
15
|
+
* and no reply to it reaches anyone - so it sends from the email config's
|
|
16
|
+
* do-not-reply address (`no-reply@EMAIL_DOMAIN` unless EMAIL_SYSTEM_FROM names
|
|
17
|
+
* another).
|
|
16
18
|
*
|
|
17
19
|
* FAIL FAST: a gate that can't email a code is useless, so if email does not
|
|
18
20
|
* resolve to SMTP mode (real delivery), this throws - unless `insecure` is set
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
*
|
|
22
24
|
* @module
|
|
23
25
|
*/
|
|
24
|
-
import { type AuthGateApi, type AuthGateConfig } from "./plugin.ts";
|
|
26
|
+
import { type AuthGateApi, type AuthGateConfig, type SendCodeOptions } from "./plugin.ts";
|
|
25
27
|
/**
|
|
26
28
|
* A code TTL as the plain phrase the email states ("10 minutes", "45 seconds").
|
|
27
29
|
*
|
|
@@ -30,6 +32,33 @@ import { type AuthGateApi, type AuthGateConfig } from "./plugin.ts";
|
|
|
30
32
|
* never told the code lives longer than it does.
|
|
31
33
|
*/
|
|
32
34
|
export declare function expiresIn(seconds: number): string;
|
|
35
|
+
/** The parts of {@link SendCodeOptions} the code email's copy is built from. */
|
|
36
|
+
type CodeCopy = Pick<SendCodeOptions, "message" | "codeTtlSeconds">;
|
|
37
|
+
/**
|
|
38
|
+
* The HTML part's source: the full branded template, with the code as a large
|
|
39
|
+
* styled heading (`## ` is what makes it prominent in an inbox).
|
|
40
|
+
*/
|
|
41
|
+
export declare function codeEmailHtmlBody(code: string, opts: CodeCopy): string;
|
|
42
|
+
/**
|
|
43
|
+
* The `text/plain` part, supplied EXPLICITLY rather than rendered from the tree
|
|
44
|
+
* above. Both parts say the same thing; only the line layout differs.
|
|
45
|
+
*
|
|
46
|
+
* The prompt and the code share ONE line ("Your verification code is: 123456").
|
|
47
|
+
* That single-line shape is what iOS, Gmail, Outlook, and Android code detection
|
|
48
|
+
* keys on most reliably - the heuristics look for a code in the same sentence as
|
|
49
|
+
* a recognized prompt, so splitting them across lines makes detection dependent
|
|
50
|
+
* on the client, and any blank line between them defeats it outright.
|
|
51
|
+
*
|
|
52
|
+
* The GENERATED text part cannot hold that shape at all: it is a rendering of the
|
|
53
|
+
* HTML, so it carries the brand header/footer and turns the code heading's CSS
|
|
54
|
+
* margin into blank lines, arriving as `prompt\n\n\ncode`.
|
|
55
|
+
*
|
|
56
|
+
* The code is visible text in BOTH parts, never an image, so a client scraping
|
|
57
|
+
* either one finds it. No trailer line follows the copy - Apple's domain-bound
|
|
58
|
+
* `@domain #code` footer is deliberately NOT emitted, since it constrains the
|
|
59
|
+
* code to one origin and is not what the broadly-compatible shape needs.
|
|
60
|
+
*/
|
|
61
|
+
export declare function codeEmailTextBody(code: string, opts: CodeCopy): string;
|
|
33
62
|
/**
|
|
34
63
|
* Boot the gate app and return the API the proxy calls. Throws when email is not
|
|
35
64
|
* in SMTP mode (no way to deliver a code) so a misconfigured gate fails fast at
|
|
@@ -37,3 +66,4 @@ export declare function expiresIn(seconds: number): string;
|
|
|
37
66
|
* fall back to insecure/open mode when the operator opted in.
|
|
38
67
|
*/
|
|
39
68
|
export declare function startGateApp(config: AuthGateConfig): Promise<AuthGateApi>;
|
|
69
|
+
export {};
|
package/lib/src/app.js
CHANGED
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
*
|
|
12
12
|
* It returns the {@link AuthGateApi} the proxy drives. `sendCode` is wired here
|
|
13
13
|
* (the plugin can't resolve HOW to send on its own) to the email plugin's
|
|
14
|
-
* transport
|
|
15
|
-
*
|
|
14
|
+
* transport. A sign-in code is SYSTEM mail - no on-behalf-of user asked for it
|
|
15
|
+
* and no reply to it reaches anyone - so it sends from the email config's
|
|
16
|
+
* do-not-reply address (`no-reply@EMAIL_DOMAIN` unless EMAIL_SYSTEM_FROM names
|
|
17
|
+
* another).
|
|
16
18
|
*
|
|
17
19
|
* FAIL FAST: a gate that can't email a code is useless, so if email does not
|
|
18
20
|
* resolve to SMTP mode (real delivery), this throws - unless `insecure` is set
|
|
@@ -39,8 +41,52 @@ export function expiresIn(seconds) {
|
|
|
39
41
|
? string.pluralize(seconds / 60, "minute")
|
|
40
42
|
: string.pluralize(seconds, "second");
|
|
41
43
|
}
|
|
44
|
+
/** The reassurance line closing both parts. */
|
|
45
|
+
const IGNORE_LINE = "If you did not request this code, you can ignore this email.";
|
|
46
|
+
/**
|
|
47
|
+
* The HTML part's source: the full branded template, with the code as a large
|
|
48
|
+
* styled heading (`## ` is what makes it prominent in an inbox).
|
|
49
|
+
*/
|
|
50
|
+
export function codeEmailHtmlBody(code, opts) {
|
|
51
|
+
return [
|
|
52
|
+
opts.message,
|
|
53
|
+
"",
|
|
54
|
+
`## ${code}`,
|
|
55
|
+
"",
|
|
56
|
+
`This code expires in ${expiresIn(opts.codeTtlSeconds)}.`,
|
|
57
|
+
"",
|
|
58
|
+
IGNORE_LINE,
|
|
59
|
+
].join("\n");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The `text/plain` part, supplied EXPLICITLY rather than rendered from the tree
|
|
63
|
+
* above. Both parts say the same thing; only the line layout differs.
|
|
64
|
+
*
|
|
65
|
+
* The prompt and the code share ONE line ("Your verification code is: 123456").
|
|
66
|
+
* That single-line shape is what iOS, Gmail, Outlook, and Android code detection
|
|
67
|
+
* keys on most reliably - the heuristics look for a code in the same sentence as
|
|
68
|
+
* a recognized prompt, so splitting them across lines makes detection dependent
|
|
69
|
+
* on the client, and any blank line between them defeats it outright.
|
|
70
|
+
*
|
|
71
|
+
* The GENERATED text part cannot hold that shape at all: it is a rendering of the
|
|
72
|
+
* HTML, so it carries the brand header/footer and turns the code heading's CSS
|
|
73
|
+
* margin into blank lines, arriving as `prompt\n\n\ncode`.
|
|
74
|
+
*
|
|
75
|
+
* The code is visible text in BOTH parts, never an image, so a client scraping
|
|
76
|
+
* either one finds it. No trailer line follows the copy - Apple's domain-bound
|
|
77
|
+
* `@domain #code` footer is deliberately NOT emitted, since it constrains the
|
|
78
|
+
* code to one origin and is not what the broadly-compatible shape needs.
|
|
79
|
+
*/
|
|
80
|
+
export function codeEmailTextBody(code, opts) {
|
|
81
|
+
return [
|
|
82
|
+
`${opts.message} ${code}`,
|
|
83
|
+
`This code expires in ${expiresIn(opts.codeTtlSeconds)}.`,
|
|
84
|
+
"",
|
|
85
|
+
IGNORE_LINE,
|
|
86
|
+
].join("\n");
|
|
87
|
+
}
|
|
42
88
|
const { createApp } = createAppNs;
|
|
43
|
-
const {
|
|
89
|
+
const { resolveSystemSenderAddress } = sender;
|
|
44
90
|
const { getEmailRuntime, sendEmail } = transport;
|
|
45
91
|
const { emailBrandFromContext } = emailBrand;
|
|
46
92
|
const { loadBrandContext } = nodeBrand;
|
|
@@ -60,30 +106,16 @@ export async function startGateApp(config) {
|
|
|
60
106
|
// `sendCode` delivers the OTP through the email plugin's SHARED transport, which
|
|
61
107
|
// the `email()` plugin primes during its `setup()` (awaited by `createApp`
|
|
62
108
|
// below). Using the module-level `sendEmail` avoids a circular dependency on the
|
|
63
|
-
// app handle's inferred type. `From` is the
|
|
64
|
-
//
|
|
109
|
+
// app handle's inferred type. The `From` is the SYSTEM sender: a verification
|
|
110
|
+
// code is machine-generated and unanswerable, so it must not arrive from a
|
|
111
|
+
// person's address inviting a reply.
|
|
65
112
|
const sendCode = async (to, code, opts) => {
|
|
66
|
-
const from =
|
|
113
|
+
const from = resolveSystemSenderAddress(getEmailRuntime().config);
|
|
67
114
|
await sendEmail({
|
|
68
115
|
to: [to],
|
|
69
116
|
subject: opts.subject,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// Outlook, and Android all detect a code from this shape and offer to
|
|
73
|
-
// autofill it, and anything more decorative is what breaks that. The code
|
|
74
|
-
// stays visible TEXT in both MIME parts (the email plugin renders the
|
|
75
|
-
// HTML and plain-text alternatives from one React Email tree), never an
|
|
76
|
-
// image, so a client that scrapes the text part still finds it.
|
|
77
|
-
body: [
|
|
78
|
-
opts.message,
|
|
79
|
-
"",
|
|
80
|
-
`## ${code}`,
|
|
81
|
-
"",
|
|
82
|
-
`This code expires in ${expiresIn(opts.codeTtlSeconds)}.`,
|
|
83
|
-
"",
|
|
84
|
-
"If you did not request this code, you can ignore this email.",
|
|
85
|
-
].join("\n"),
|
|
86
|
-
}, from);
|
|
117
|
+
body: codeEmailHtmlBody(code, opts),
|
|
118
|
+
}, from, undefined, { text: codeEmailTextBody(code, opts) });
|
|
87
119
|
};
|
|
88
120
|
// `createApp` namespaces each plugin's exports on the handle by manifest name;
|
|
89
121
|
// `handle.authGate` is the in-process gate API the proxy drives.
|
|
@@ -111,4 +143,4 @@ export async function startGateApp(config) {
|
|
|
111
143
|
logger.info("gate app ready (no server; proxy-driven)");
|
|
112
144
|
return handle.authGate;
|
|
113
145
|
}
|
|
114
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUVILE9BQU8sRUFBRSxTQUFTLElBQUksV0FBVyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDN0QsT0FBTyxFQUFFLEtBQUssSUFBSSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsS0FBSyxJQUFJLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDckQsT0FBTyxFQUFFLFFBQVEsRUFBeUMsTUFBTSxhQUFhLENBQUM7QUFFOUUsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUV4Qzs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLE9BQWU7SUFDdkMsT0FBTyxPQUFPLElBQUksRUFBRSxJQUFJLE9BQU8sR0FBRyxFQUFFLEtBQUssQ0FBQztRQUN4QyxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEdBQUcsRUFBRSxFQUFFLFFBQVEsQ0FBQztRQUMxQyxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDMUMsQ0FBQztBQUVELE1BQU0sRUFBRSxTQUFTLEVBQUUsR0FBRyxXQUFXLENBQUM7QUFDbEMsTUFBTSxFQUFFLG9CQUFvQixFQUFFLEdBQUcsTUFBTSxDQUFDO0FBQ3hDLE1BQU0sRUFBRSxlQUFlLEVBQUUsU0FBUyxFQUFFLEdBQUcsU0FBUyxDQUFDO0FBQ2pELE1BQU0sRUFBRSxxQkFBcUIsRUFBRSxHQUFHLFVBQVUsQ0FBQztBQUM3QyxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsR0FBRyxTQUFTLENBQUM7QUFFdkM7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLFlBQVksQ0FBQyxNQUFzQjtJQUN2RCw4RUFBOEU7SUFDOUUsOEVBQThFO0lBQzlFLDZFQUE2RTtJQUM3RSw2RUFBNkU7SUFDN0UseUVBQXlFO0lBQ3pFLE1BQU0sT0FBTyxHQUFHLE1BQU0sZ0JBQWdCLEVBQUUsQ0FBQztJQUV6QyxpRkFBaUY7SUFDakYsMkVBQTJFO0lBQzNFLGlGQUFpRjtJQUNqRixrRkFBa0Y7SUFDbEYsa0ZBQWtGO0lBQ2xGLE1BQU0sUUFBUSxHQUE0QyxLQUFLLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsRUFBRTtRQUNqRixNQUFNLElBQUksR0FBRyxvQkFBb0IsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDdkUsTUFBTSxTQUFTLENBQ2I7WUFDRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDUixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDckIsdUVBQXVFO1lBQ3ZFLDBFQUEwRTtZQUMxRSxzRUFBc0U7WUFDdEUsMEVBQTBFO1lBQzFFLHNFQUFzRTtZQUN0RSx3RUFBd0U7WUFDeEUsZ0VBQWdFO1lBQ2hFLElBQUksRUFBRTtnQkFDSixJQUFJLENBQUMsT0FBTztnQkFDWixFQUFFO2dCQUNGLE1BQU0sSUFBSSxFQUFFO2dCQUNaLEVBQUU7Z0JBQ0Ysd0JBQXdCLFNBQVMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUc7Z0JBQ3pELEVBQUU7Z0JBQ0YsOERBQThEO2FBQy9ELENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztTQUNiLEVBQ0QsSUFBSSxDQUNMLENBQUM7SUFDSixDQUFDLENBQUM7SUFFRiwrRUFBK0U7SUFDL0UsaUVBQWlFO0lBQ2pFLE1BQU0sTUFBTSxHQUFHLE1BQU0sU0FBUyxDQUFDO1FBQzdCLE9BQU8sRUFBRTtZQUNQLHdFQUF3RTtZQUN4RSw0RUFBNEU7WUFDNUUsMEVBQTBFO1lBQzFFLEtBQUssQ0FBQyxFQUFFLEtBQUssRUFBRSxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ2hELHdFQUF3RTtZQUN4RSw0RUFBNEU7WUFDNUUscUVBQXFFO1lBQ3JFLDJFQUEyRTtZQUMzRSxnRUFBZ0U7WUFDaEUsUUFBUSxDQUFDLEVBQUUsR0FBRyxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQztTQUMvRTtLQUNGLENBQUMsQ0FBQztJQUVILGlGQUFpRjtJQUNqRixnRkFBZ0Y7SUFDaEYsaUZBQWlGO0lBQ2pGLElBQUksZUFBZSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUM3QyxNQUFNLElBQUksS0FBSyxDQUNiLDhFQUE4RTtZQUM1RSwwR0FBMEcsQ0FDN0csQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLENBQUMsSUFBSSxDQUFDLDBDQUEwQyxDQUFDLENBQUM7SUFDeEQsT0FBTyxNQUFNLENBQUMsUUFBdUIsQ0FBQztBQUN4QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgdHVubmVsIGdhdGUncyB0aW55IEFwcEtpdCBcImFwcFwiIC0gYGNyZWF0ZUFwcGAgV0lUSE9VVCBhIGBzZXJ2ZXIoKWAgcGx1Z2luLlxuICpcbiAqIFRoZXJlIGlzIG5vIEhUVFAgc2VydmVyIGhlcmU6IHRoZSB0dW5uZWwgcHJveHkgaXMgdGhlIHNlcnZlciwgYW5kIGl0IGNhbGxzIHRoZVxuICogZ2F0ZSBoYW5kbGVycyBpbi1wcm9jZXNzLiBgY3JlYXRlQXBwYCBpcyB1c2VkIG9ubHkgZm9yIHdoYXQgaXQgYXV0by13aXJlczpcbiAqICAgLSBgQ2FjaGVNYW5hZ2VyYCAobWVtb3J5LCBvciBMYWtlYmFzZSB3aGVuIHRoZSBkZXBsb3kgY29uZmlndXJlcyBwZXJzaXN0ZW50XG4gKiAgICAgY2FjaGUgc3RvcmFnZSkgLSB3aGljaCB0aGUgT1RQIGBDb2RlU3RvcmVgIHVzZXMgZm9yIHN0b3JhZ2UgKyBUVEwgZXZpY3Rpb247XG4gKiAgIC0gdGhlIGBlbWFpbCgpYCB0cmFuc3BvcnQgKFNNVFAgLyBvdXRib3gpLCBwcmltZWQgZnJvbSBlbnYsIHNvIGBzZW5kQ29kZWAgY2FuXG4gKiAgICAgZGVsaXZlciB0aGUgb25lLXRpbWUgY29kZTtcbiAqICAgLSBkYngtdG9vbHMgYXV0by1jb25maWd1cmF0aW9uICsgYnJhbmRpbmcgdmlhIGBAZGJ4LXRvb2xzL2FwcGtpdGAuXG4gKlxuICogSXQgcmV0dXJucyB0aGUge0BsaW5rIEF1dGhHYXRlQXBpfSB0aGUgcHJveHkgZHJpdmVzLiBgc2VuZENvZGVgIGlzIHdpcmVkIGhlcmVcbiAqICh0aGUgcGx1Z2luIGNhbid0IHJlc29sdmUgSE9XIHRvIHNlbmQgb24gaXRzIG93bikgdG8gdGhlIGVtYWlsIHBsdWdpbidzXG4gKiB0cmFuc3BvcnQsIHJlc29sdmluZyB0aGUgYEZyb21gIGZyb20gdGhlIGVtYWlsIHJ1bnRpbWUgY29uZmlnIChFTUFJTF9GUk9NIC9cbiAqIEVNQUlMX0RPTUFJTikgc2luY2UgYW4gT1RQIHJlcXVlc3QgaGFzIG5vIG9uLWJlaGFsZi1vZiB1c2VyLlxuICpcbiAqIEZBSUwgRkFTVDogYSBnYXRlIHRoYXQgY2FuJ3QgZW1haWwgYSBjb2RlIGlzIHVzZWxlc3MsIHNvIGlmIGVtYWlsIGRvZXMgbm90XG4gKiByZXNvbHZlIHRvIFNNVFAgbW9kZSAocmVhbCBkZWxpdmVyeSksIHRoaXMgdGhyb3dzIC0gdW5sZXNzIGBpbnNlY3VyZWAgaXMgc2V0XG4gKiAoYC0taW5zZWN1cmVgIC8gYFRVTk5FTF9JTlNFQ1VSRT10cnVlYCksIGluIHdoaWNoIGNhc2UgdGhlIGNhbGxlciBydW5zIHRoZVxuICogdHVubmVsIE9QRU4gd2l0aCBubyBnYXRlLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVBcHAgYXMgY3JlYXRlQXBwTnMgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGJyYW5kIGFzIG5vZGVCcmFuZCB9IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmVcIjtcbmltcG9ydCB7IGJyYW5kIGFzIGVtYWlsQnJhbmQsIGVtYWlsLCBzZW5kZXIsIHRyYW5zcG9ydCB9IGZyb20gXCJAZGJ4LXRvb2xzL2VtYWlsXCI7XG5pbXBvcnQgeyBsb2csIHN0cmluZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBhdXRoR2F0ZSwgdHlwZSBBdXRoR2F0ZUFwaSwgdHlwZSBBdXRoR2F0ZUNvbmZpZyB9IGZyb20gXCIuL3BsdWdpbi50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsOmFwcFwiKTtcblxuLyoqXG4gKiBBIGNvZGUgVFRMIGFzIHRoZSBwbGFpbiBwaHJhc2UgdGhlIGVtYWlsIHN0YXRlcyAoXCIxMCBtaW51dGVzXCIsIFwiNDUgc2Vjb25kc1wiKS5cbiAqXG4gKiBXaG9sZSBtaW51dGVzIHJlYWQgYXMgbWludXRlczsgYW55dGhpbmcgZWxzZSBzdGF5cyBpbiBzZWNvbmRzIHJhdGhlciB0aGFuXG4gKiByb3VuZGluZywgc28gYSA5MC1zZWNvbmQgVFRMIGlzIG5vdCBhZHZlcnRpc2VkIGFzIFwiMSBtaW51dGVcIiBhbmQgYSByZWNpcGllbnQgaXNcbiAqIG5ldmVyIHRvbGQgdGhlIGNvZGUgbGl2ZXMgbG9uZ2VyIHRoYW4gaXQgZG9lcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4cGlyZXNJbihzZWNvbmRzOiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gc2Vjb25kcyA+PSA2MCAmJiBzZWNvbmRzICUgNjAgPT09IDBcbiAgICA/IHN0cmluZy5wbHVyYWxpemUoc2Vjb25kcyAvIDYwLCBcIm1pbnV0ZVwiKVxuICAgIDogc3RyaW5nLnBsdXJhbGl6ZShzZWNvbmRzLCBcInNlY29uZFwiKTtcbn1cblxuY29uc3QgeyBjcmVhdGVBcHAgfSA9IGNyZWF0ZUFwcE5zO1xuY29uc3QgeyByZXNvbHZlU2VuZGVyQWRkcmVzcyB9ID0gc2VuZGVyO1xuY29uc3QgeyBnZXRFbWFpbFJ1bnRpbWUsIHNlbmRFbWFpbCB9ID0gdHJhbnNwb3J0O1xuY29uc3QgeyBlbWFpbEJyYW5kRnJvbUNvbnRleHQgfSA9IGVtYWlsQnJhbmQ7XG5jb25zdCB7IGxvYWRCcmFuZENvbnRleHQgfSA9IG5vZGVCcmFuZDtcblxuLyoqXG4gKiBCb290IHRoZSBnYXRlIGFwcCBhbmQgcmV0dXJuIHRoZSBBUEkgdGhlIHByb3h5IGNhbGxzLiBUaHJvd3Mgd2hlbiBlbWFpbCBpcyBub3RcbiAqIGluIFNNVFAgbW9kZSAobm8gd2F5IHRvIGRlbGl2ZXIgYSBjb2RlKSBzbyBhIG1pc2NvbmZpZ3VyZWQgZ2F0ZSBmYWlscyBmYXN0IGF0XG4gKiBzdGFydHVwIHJhdGhlciB0aGFuIHNpbGVudGx5IGFjY2VwdGluZyBub2JvZHk7IHRoZSBjYWxsZXIgbWF5IGNhdGNoIHRoaXMgYW5kXG4gKiBmYWxsIGJhY2sgdG8gaW5zZWN1cmUvb3BlbiBtb2RlIHdoZW4gdGhlIG9wZXJhdG9yIG9wdGVkIGluLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RhcnRHYXRlQXBwKGNvbmZpZzogQXV0aEdhdGVDb25maWcpOiBQcm9taXNlPEF1dGhHYXRlQXBpPiB7XG4gIC8vIFRoZSBob3N0IGFwcCdzIG93biBicmFuZCAoYGJyYW5kaW5nL2JyYW5kLnlhbWxgIGRpc2NvdmVyZWQgZnJvbSBjd2QpIG9yIHRoZVxuICAvLyBkYngtdG9vbHMgZGVmYXVsdC4gVGhpcyBpcyB0aGUgT05FIGJyYW5kIHNvdXJjZSBmb3IgdGhlIGdhdGU6IGl0IHN0eWxlcyB0aGVcbiAgLy8gY29kZSBlbWFpbCAoYWNjZW50IGJhbmQsIGZvbnQsIGxvZ28pIHZpYSB0aGUgZW1haWwgcGx1Z2luIEFORCBzdXBwbGllcyB0aGVcbiAgLy8gZGlzcGxheSBuYW1lIHRoZSBjb3B5IHVzZXMsIHNvIGEgZGVwbG95bWVudCB0aGF0IHRoZW1lcyBpdHMgYXBwIHRoZW1lcyBpdHNcbiAgLy8gc2lnbi1pbiBlbWFpbCB3aXRoIGl0LiBBbiBleHBsaWNpdCBgYnJhbmROYW1lYCBzdGlsbCB3aW5zIChzZWUgYmVsb3cpLlxuICBjb25zdCBjb250ZXh0ID0gYXdhaXQgbG9hZEJyYW5kQ29udGV4dCgpO1xuXG4gIC8vIGBzZW5kQ29kZWAgZGVsaXZlcnMgdGhlIE9UUCB0aHJvdWdoIHRoZSBlbWFpbCBwbHVnaW4ncyBTSEFSRUQgdHJhbnNwb3J0LCB3aGljaFxuICAvLyB0aGUgYGVtYWlsKClgIHBsdWdpbiBwcmltZXMgZHVyaW5nIGl0cyBgc2V0dXAoKWAgKGF3YWl0ZWQgYnkgYGNyZWF0ZUFwcGBcbiAgLy8gYmVsb3cpLiBVc2luZyB0aGUgbW9kdWxlLWxldmVsIGBzZW5kRW1haWxgIGF2b2lkcyBhIGNpcmN1bGFyIGRlcGVuZGVuY3kgb24gdGhlXG4gIC8vIGFwcCBoYW5kbGUncyBpbmZlcnJlZCB0eXBlLiBgRnJvbWAgaXMgdGhlIGFwcCdzIGNvbmZpZ3VyZWQgc2VuZGVyIChFTUFJTF9GUk9NIC9cbiAgLy8gRU1BSUxfRE9NQUlOKTsgdGhlIGNvZGUgZW1haWwgaGFzIG5vIE9CTyB1c2VyLCBzbyBpdCByZXNvbHZlcyB3aXRoIGB1bmRlZmluZWRgLlxuICBjb25zdCBzZW5kQ29kZTogTm9uTnVsbGFibGU8QXV0aEdhdGVDb25maWdbXCJzZW5kQ29kZVwiXT4gPSBhc3luYyAodG8sIGNvZGUsIG9wdHMpID0+IHtcbiAgICBjb25zdCBmcm9tID0gcmVzb2x2ZVNlbmRlckFkZHJlc3MoZ2V0RW1haWxSdW50aW1lKCkuY29uZmlnLCB1bmRlZmluZWQpO1xuICAgIGF3YWl0IHNlbmRFbWFpbChcbiAgICAgIHtcbiAgICAgICAgdG86IFt0b10sXG4gICAgICAgIHN1YmplY3Q6IG9wdHMuc3ViamVjdCxcbiAgICAgICAgLy8gRGVsaWJlcmF0ZWx5IHRoZSBjb252ZW50aW9uYWwgb25lLXRpbWUtY29kZSBsYXlvdXQ6IHRoZSBwcm9tcHQgbGluZSxcbiAgICAgICAgLy8gdGhlbiB0aGUgYmFyZSBjb2RlIEFMT05FIG9uIHRoZSBuZXh0IGxpbmUsIHRoZW4gdGhlIGV4cGlyeS4gaU9TLCBHbWFpbCxcbiAgICAgICAgLy8gT3V0bG9vaywgYW5kIEFuZHJvaWQgYWxsIGRldGVjdCBhIGNvZGUgZnJvbSB0aGlzIHNoYXBlIGFuZCBvZmZlciB0b1xuICAgICAgICAvLyBhdXRvZmlsbCBpdCwgYW5kIGFueXRoaW5nIG1vcmUgZGVjb3JhdGl2ZSBpcyB3aGF0IGJyZWFrcyB0aGF0LiBUaGUgY29kZVxuICAgICAgICAvLyBzdGF5cyB2aXNpYmxlIFRFWFQgaW4gYm90aCBNSU1FIHBhcnRzICh0aGUgZW1haWwgcGx1Z2luIHJlbmRlcnMgdGhlXG4gICAgICAgIC8vIEhUTUwgYW5kIHBsYWluLXRleHQgYWx0ZXJuYXRpdmVzIGZyb20gb25lIFJlYWN0IEVtYWlsIHRyZWUpLCBuZXZlciBhblxuICAgICAgICAvLyBpbWFnZSwgc28gYSBjbGllbnQgdGhhdCBzY3JhcGVzIHRoZSB0ZXh0IHBhcnQgc3RpbGwgZmluZHMgaXQuXG4gICAgICAgIGJvZHk6IFtcbiAgICAgICAgICBvcHRzLm1lc3NhZ2UsXG4gICAgICAgICAgXCJcIixcbiAgICAgICAgICBgIyMgJHtjb2RlfWAsXG4gICAgICAgICAgXCJcIixcbiAgICAgICAgICBgVGhpcyBjb2RlIGV4cGlyZXMgaW4gJHtleHBpcmVzSW4ob3B0cy5jb2RlVHRsU2Vjb25kcyl9LmAsXG4gICAgICAgICAgXCJcIixcbiAgICAgICAgICBcIklmIHlvdSBkaWQgbm90IHJlcXVlc3QgdGhpcyBjb2RlLCB5b3UgY2FuIGlnbm9yZSB0aGlzIGVtYWlsLlwiLFxuICAgICAgICBdLmpvaW4oXCJcXG5cIiksXG4gICAgICB9LFxuICAgICAgZnJvbSxcbiAgICApO1xuICB9O1xuXG4gIC8vIGBjcmVhdGVBcHBgIG5hbWVzcGFjZXMgZWFjaCBwbHVnaW4ncyBleHBvcnRzIG9uIHRoZSBoYW5kbGUgYnkgbWFuaWZlc3QgbmFtZTtcbiAgLy8gYGhhbmRsZS5hdXRoR2F0ZWAgaXMgdGhlIGluLXByb2Nlc3MgZ2F0ZSBBUEkgdGhlIHByb3h5IGRyaXZlcy5cbiAgY29uc3QgaGFuZGxlID0gYXdhaXQgY3JlYXRlQXBwKHtcbiAgICBwbHVnaW5zOiBbXG4gICAgICAvLyBCcmFuZCB0aGUgY29kZSBlbWFpbCBmcm9tIHRoZSByZXNvbHZlZCBjb250ZXh0LCB0aGUgc2FtZSBicmlkZ2UgZXZlcnlcbiAgICAgIC8vIG90aGVyIGRieC10b29scyBlbWFpbCBzdXJmYWNlIHVzZXMgKGFjY2VudCArIGZvbnQgaW5saW5lZCwgbG9nbyBvbmx5IHdoZW5cbiAgICAgIC8vIGl0IGlzIGEgZmV0Y2hhYmxlIFVSTCAtIGEgcGFja2FnZS1leHBvcnQgcGF0aCBjYW5ub3QgbG9hZCBpbiBhbiBpbmJveCkuXG4gICAgICBlbWFpbCh7IGJyYW5kOiBlbWFpbEJyYW5kRnJvbUNvbnRleHQoY29udGV4dCkgfSksXG4gICAgICAvLyBgYnJhbmROYW1lYCBmYWxscyBiYWNrIHRvIHRoZSByZXNvbHZlZCBjb250ZXh0J3MgZGlzcGxheSBuYW1lLCBzbyB0aGVcbiAgICAgIC8vIGVtYWlsIGNvcHkgbmFtZXMgdGhlIGFwcCByYXRoZXIgdGhhbiBhIGdlbmVyaWMgcGxhY2Vob2xkZXIuIFNwZWxsZWQgYXMgYW5cbiAgICAgIC8vIGV4cGxpY2l0IGA/P2AgcmF0aGVyIHRoYW4gYSBrZXkgYmVmb3JlIGAuLi5jb25maWdgOiBjb21tYW5kZXIgc2V0c1xuICAgICAgLy8gYGJyYW5kTmFtZWAgb24gdGhlIG9wdGlvbnMgb2JqZWN0IHdoZXRoZXIgb3Igbm90IHRoZSBmbGFnIHdhcyBwYXNzZWQsIHNvXG4gICAgICAvLyBzcHJlYWRpbmcgaXQgd291bGQgY2xvYmJlciB0aGUgY29udGV4dCBuYW1lIHdpdGggYHVuZGVmaW5lZGAuXG4gICAgICBhdXRoR2F0ZSh7IC4uLmNvbmZpZywgYnJhbmROYW1lOiBjb25maWcuYnJhbmROYW1lID8/IGNvbnRleHQubmFtZSwgc2VuZENvZGUgfSksXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gRmFpbCBmYXN0OiB0aGUgZ2F0ZSBuZWVkcyBTTVRQIHRvIGVtYWlsIGNvZGVzLiBgZ2V0RW1haWxSdW50aW1lKClgIHJlc29sdmVzIHRvXG4gIC8vIGBtb2RlOiBcImZpbGVcImAgKG91dGJveCkgb3IgdGhyb3dzIHdoZW4gbm8gU01UUCBjcmVkcyBhcmUgY29uZmlndXJlZCAtIG5laXRoZXJcbiAgLy8gY2FuIGRlbGl2ZXIgdG8gYSByZWFsIGluYm94LCBzbyByZWZ1c2UgdG8gYnJpbmcgdXAgYSBnYXRlIHRoYXQgbGV0cyBub2JvZHkgaW4uXG4gIGlmIChnZXRFbWFpbFJ1bnRpbWUoKS5jb25maWcubW9kZSAhPT0gXCJzbXRwXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBcImVtYWlsIGlzIG5vdCBjb25maWd1cmVkIGZvciBTTVRQIGRlbGl2ZXJ5IC0gdGhlIE9UUCBnYXRlIGNhbm5vdCBzZW5kIGNvZGVzLiBcIiArXG4gICAgICAgIFwiU2V0IFNNVFBfSE9TVC9TTVRQX1VTRVIvU01UUF9QQVNTV09SRCwgb3IgcGFzcyAtLWluc2VjdXJlIC8gVFVOTkVMX0lOU0VDVVJFPXRydWUgdG8gcnVuIHRoZSB0dW5uZWwgb3Blbi5cIixcbiAgICApO1xuICB9XG5cbiAgbG9nZ2VyLmluZm8oXCJnYXRlIGFwcCByZWFkeSAobm8gc2VydmVyOyBwcm94eS1kcml2ZW4pXCIpO1xuICByZXR1cm4gaGFuZGxlLmF1dGhHYXRlIGFzIEF1dGhHYXRlQXBpO1xufVxuIl19
|
|
146
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBRUgsT0FBTyxFQUFFLFNBQVMsSUFBSSxXQUFXLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsS0FBSyxJQUFJLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxLQUFLLElBQUksVUFBVSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDakYsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsUUFBUSxFQUErRCxNQUFNLGFBQWEsQ0FBQztBQUVwRyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBRXhDOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQUMsT0FBZTtJQUN2QyxPQUFPLE9BQU8sSUFBSSxFQUFFLElBQUksT0FBTyxHQUFHLEVBQUUsS0FBSyxDQUFDO1FBQ3hDLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE9BQU8sR0FBRyxFQUFFLEVBQUUsUUFBUSxDQUFDO1FBQzFDLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztBQUMxQyxDQUFDO0FBS0QsK0NBQStDO0FBQy9DLE1BQU0sV0FBVyxHQUFHLDhEQUE4RCxDQUFDO0FBRW5GOzs7R0FHRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxJQUFZLEVBQUUsSUFBYztJQUM1RCxPQUFPO1FBQ0wsSUFBSSxDQUFDLE9BQU87UUFDWixFQUFFO1FBQ0YsTUFBTSxJQUFJLEVBQUU7UUFDWixFQUFFO1FBQ0Ysd0JBQXdCLFNBQVMs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XG4gKiBUaGUgdHVubmVsIGdhdGUncyB0aW55IEFwcEtpdCBcImFwcFwiIC0gYGNyZWF0ZUFwcGAgV0lUSE9VVCBhIGBzZXJ2ZXIoKWAgcGx1Z2luLlxuICpcbiAqIFRoZXJlIGlzIG5vIEhUVFAgc2VydmVyIGhlcmU6IHRoZSB0dW5uZWwgcHJveHkgaXMgdGhlIHNlcnZlciwgYW5kIGl0IGNhbGxzIHRoZVxuICogZ2F0ZSBoYW5kbGVycyBpbi1wcm9jZXNzLiBgY3JlYXRlQXBwYCBpcyB1c2VkIG9ubHkgZm9yIHdoYXQgaXQgYXV0by13aXJlczpcbiAqICAgLSBgQ2FjaGVNYW5hZ2VyYCAobWVtb3J5LCBvciBMYWtlYmFzZSB3aGVuIHRoZSBkZXBsb3kgY29uZmlndXJlcyBwZXJzaXN0ZW50XG4gKiAgICAgY2FjaGUgc3RvcmFnZSkgLSB3aGljaCB0aGUgT1RQIGBDb2RlU3RvcmVgIHVzZXMgZm9yIHN0b3JhZ2UgKyBUVEwgZXZpY3Rpb247XG4gKiAgIC0gdGhlIGBlbWFpbCgpYCB0cmFuc3BvcnQgKFNNVFAgLyBvdXRib3gpLCBwcmltZWQgZnJvbSBlbnYsIHNvIGBzZW5kQ29kZWAgY2FuXG4gKiAgICAgZGVsaXZlciB0aGUgb25lLXRpbWUgY29kZTtcbiAqICAgLSBkYngtdG9vbHMgYXV0by1jb25maWd1cmF0aW9uICsgYnJhbmRpbmcgdmlhIGBAZGJ4LXRvb2xzL2FwcGtpdGAuXG4gKlxuICogSXQgcmV0dXJucyB0aGUge0BsaW5rIEF1dGhHYXRlQXBpfSB0aGUgcHJveHkgZHJpdmVzLiBgc2VuZENvZGVgIGlzIHdpcmVkIGhlcmVcbiAqICh0aGUgcGx1Z2luIGNhbid0IHJlc29sdmUgSE9XIHRvIHNlbmQgb24gaXRzIG93bikgdG8gdGhlIGVtYWlsIHBsdWdpbidzXG4gKiB0cmFuc3BvcnQuIEEgc2lnbi1pbiBjb2RlIGlzIFNZU1RFTSBtYWlsIC0gbm8gb24tYmVoYWxmLW9mIHVzZXIgYXNrZWQgZm9yIGl0XG4gKiBhbmQgbm8gcmVwbHkgdG8gaXQgcmVhY2hlcyBhbnlvbmUgLSBzbyBpdCBzZW5kcyBmcm9tIHRoZSBlbWFpbCBjb25maWcnc1xuICogZG8tbm90LXJlcGx5IGFkZHJlc3MgKGBuby1yZXBseUBFTUFJTF9ET01BSU5gIHVubGVzcyBFTUFJTF9TWVNURU1fRlJPTSBuYW1lc1xuICogYW5vdGhlcikuXG4gKlxuICogRkFJTCBGQVNUOiBhIGdhdGUgdGhhdCBjYW4ndCBlbWFpbCBhIGNvZGUgaXMgdXNlbGVzcywgc28gaWYgZW1haWwgZG9lcyBub3RcbiAqIHJlc29sdmUgdG8gU01UUCBtb2RlIChyZWFsIGRlbGl2ZXJ5KSwgdGhpcyB0aHJvd3MgLSB1bmxlc3MgYGluc2VjdXJlYCBpcyBzZXRcbiAqIChgLS1pbnNlY3VyZWAgLyBgVFVOTkVMX0lOU0VDVVJFPXRydWVgKSwgaW4gd2hpY2ggY2FzZSB0aGUgY2FsbGVyIHJ1bnMgdGhlXG4gKiB0dW5uZWwgT1BFTiB3aXRoIG5vIGdhdGUuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUFwcCBhcyBjcmVhdGVBcHBOcyB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuaW1wb3J0IHsgYnJhbmQgYXMgbm9kZUJyYW5kIH0gZnJvbSBcIkBkYngtdG9vbHMvY29yZVwiO1xuaW1wb3J0IHsgYnJhbmQgYXMgZW1haWxCcmFuZCwgZW1haWwsIHNlbmRlciwgdHJhbnNwb3J0IH0gZnJvbSBcIkBkYngtdG9vbHMvZW1haWxcIjtcbmltcG9ydCB7IGxvZywgc3RyaW5nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGF1dGhHYXRlLCB0eXBlIEF1dGhHYXRlQXBpLCB0eXBlIEF1dGhHYXRlQ29uZmlnLCB0eXBlIFNlbmRDb2RlT3B0aW9ucyB9IGZyb20gXCIuL3BsdWdpbi50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsOmFwcFwiKTtcblxuLyoqXG4gKiBBIGNvZGUgVFRMIGFzIHRoZSBwbGFpbiBwaHJhc2UgdGhlIGVtYWlsIHN0YXRlcyAoXCIxMCBtaW51dGVzXCIsIFwiNDUgc2Vjb25kc1wiKS5cbiAqXG4gKiBXaG9sZSBtaW51dGVzIHJlYWQgYXMgbWludXRlczsgYW55dGhpbmcgZWxzZSBzdGF5cyBpbiBzZWNvbmRzIHJhdGhlciB0aGFuXG4gKiByb3VuZGluZywgc28gYSA5MC1zZWNvbmQgVFRMIGlzIG5vdCBhZHZlcnRpc2VkIGFzIFwiMSBtaW51dGVcIiBhbmQgYSByZWNpcGllbnQgaXNcbiAqIG5ldmVyIHRvbGQgdGhlIGNvZGUgbGl2ZXMgbG9uZ2VyIHRoYW4gaXQgZG9lcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4cGlyZXNJbihzZWNvbmRzOiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gc2Vjb25kcyA+PSA2MCAmJiBzZWNvbmRzICUgNjAgPT09IDBcbiAgICA/IHN0cmluZy5wbHVyYWxpemUoc2Vjb25kcyAvIDYwLCBcIm1pbnV0ZVwiKVxuICAgIDogc3RyaW5nLnBsdXJhbGl6ZShzZWNvbmRzLCBcInNlY29uZFwiKTtcbn1cblxuLyoqIFRoZSBwYXJ0cyBvZiB7QGxpbmsgU2VuZENvZGVPcHRpb25zfSB0aGUgY29kZSBlbWFpbCdzIGNvcHkgaXMgYnVpbHQgZnJvbS4gKi9cbnR5cGUgQ29kZUNvcHkgPSBQaWNrPFNlbmRDb2RlT3B0aW9ucywgXCJtZXNzYWdlXCIgfCBcImNvZGVUdGxTZWNvbmRzXCI+O1xuXG4vKiogVGhlIHJlYXNzdXJhbmNlIGxpbmUgY2xvc2luZyBib3RoIHBhcnRzLiAqL1xuY29uc3QgSUdOT1JFX0xJTkUgPSBcIklmIHlvdSBkaWQgbm90IHJlcXVlc3QgdGhpcyBjb2RlLCB5b3UgY2FuIGlnbm9yZSB0aGlzIGVtYWlsLlwiO1xuXG4vKipcbiAqIFRoZSBIVE1MIHBhcnQncyBzb3VyY2U6IHRoZSBmdWxsIGJyYW5kZWQgdGVtcGxhdGUsIHdpdGggdGhlIGNvZGUgYXMgYSBsYXJnZVxuICogc3R5bGVkIGhlYWRpbmcgKGAjIyBgIGlzIHdoYXQgbWFrZXMgaXQgcHJvbWluZW50IGluIGFuIGluYm94KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvZGVFbWFpbEh0bWxCb2R5KGNvZGU6IHN0cmluZywgb3B0czogQ29kZUNvcHkpOiBzdHJpbmcge1xuICByZXR1cm4gW1xuICAgIG9wdHMubWVzc2FnZSxcbiAgICBcIlwiLFxuICAgIGAjIyAke2NvZGV9YCxcbiAgICBcIlwiLFxuICAgIGBUaGlzIGNvZGUgZXhwaXJlcyBpbiAke2V4cGlyZXNJbihvcHRzLmNvZGVUdGxTZWNvbmRzKX0uYCxcbiAgICBcIlwiLFxuICAgIElHTk9SRV9MSU5FLFxuICBdLmpvaW4oXCJcXG5cIik7XG59XG5cbi8qKlxuICogVGhlIGB0ZXh0L3BsYWluYCBwYXJ0LCBzdXBwbGllZCBFWFBMSUNJVExZIHJhdGhlciB0aGFuIHJlbmRlcmVkIGZyb20gdGhlIHRyZWVcbiAqIGFib3ZlLiBCb3RoIHBhcnRzIHNheSB0aGUgc2FtZSB0aGluZzsgb25seSB0aGUgbGluZSBsYXlvdXQgZGlmZmVycy5cbiAqXG4gKiBUaGUgcHJvbXB0IGFuZCB0aGUgY29kZSBzaGFyZSBPTkUgbGluZSAoXCJZb3VyIHZlcmlmaWNhdGlvbiBjb2RlIGlzOiAxMjM0NTZcIikuXG4gKiBUaGF0IHNpbmdsZS1saW5lIHNoYXBlIGlzIHdoYXQgaU9TLCBHbWFpbCwgT3V0bG9vaywgYW5kIEFuZHJvaWQgY29kZSBkZXRlY3Rpb25cbiAqIGtleXMgb24gbW9zdCByZWxpYWJseSAtIHRoZSBoZXVyaXN0aWNzIGxvb2sgZm9yIGEgY29kZSBpbiB0aGUgc2FtZSBzZW50ZW5jZSBhc1xuICogYSByZWNvZ25pemVkIHByb21wdCwgc28gc3BsaXR0aW5nIHRoZW0gYWNyb3NzIGxpbmVzIG1ha2VzIGRldGVjdGlvbiBkZXBlbmRlbnRcbiAqIG9uIHRoZSBjbGllbnQsIGFuZCBhbnkgYmxhbmsgbGluZSBiZXR3ZWVuIHRoZW0gZGVmZWF0cyBpdCBvdXRyaWdodC5cbiAqXG4gKiBUaGUgR0VORVJBVEVEIHRleHQgcGFydCBjYW5ub3QgaG9sZCB0aGF0IHNoYXBlIGF0IGFsbDogaXQgaXMgYSByZW5kZXJpbmcgb2YgdGhlXG4gKiBIVE1MLCBzbyBpdCBjYXJyaWVzIHRoZSBicmFuZCBoZWFkZXIvZm9vdGVyIGFuZCB0dXJucyB0aGUgY29kZSBoZWFkaW5nJ3MgQ1NTXG4gKiBtYXJnaW4gaW50byBibGFuayBsaW5lcywgYXJyaXZpbmcgYXMgYHByb21wdFxcblxcblxcbmNvZGVgLlxuICpcbiAqIFRoZSBjb2RlIGlzIHZpc2libGUgdGV4dCBpbiBCT1RIIHBhcnRzLCBuZXZlciBhbiBpbWFnZSwgc28gYSBjbGllbnQgc2NyYXBpbmdcbiAqIGVpdGhlciBvbmUgZmluZHMgaXQuIE5vIHRyYWlsZXIgbGluZSBmb2xsb3dzIHRoZSBjb3B5IC0gQXBwbGUncyBkb21haW4tYm91bmRcbiAqIGBAZG9tYWluICNjb2RlYCBmb290ZXIgaXMgZGVsaWJlcmF0ZWx5IE5PVCBlbWl0dGVkLCBzaW5jZSBpdCBjb25zdHJhaW5zIHRoZVxuICogY29kZSB0byBvbmUgb3JpZ2luIGFuZCBpcyBub3Qgd2hhdCB0aGUgYnJvYWRseS1jb21wYXRpYmxlIHNoYXBlIG5lZWRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29kZUVtYWlsVGV4dEJvZHkoY29kZTogc3RyaW5nLCBvcHRzOiBDb2RlQ29weSk6IHN0cmluZyB7XG4gIHJldHVybiBbXG4gICAgYCR7b3B0cy5tZXNzYWdlfSAke2NvZGV9YCxcbiAgICBgVGhpcyBjb2RlIGV4cGlyZXMgaW4gJHtleHBpcmVzSW4ob3B0cy5jb2RlVHRsU2Vjb25kcyl9LmAsXG4gICAgXCJcIixcbiAgICBJR05PUkVfTElORSxcbiAgXS5qb2luKFwiXFxuXCIpO1xufVxuXG5jb25zdCB7IGNyZWF0ZUFwcCB9ID0gY3JlYXRlQXBwTnM7XG5jb25zdCB7IHJlc29sdmVTeXN0ZW1TZW5kZXJBZGRyZXNzIH0gPSBzZW5kZXI7XG5jb25zdCB7IGdldEVtYWlsUnVudGltZSwgc2VuZEVtYWlsIH0gPSB0cmFuc3BvcnQ7XG5jb25zdCB7IGVtYWlsQnJhbmRGcm9tQ29udGV4dCB9ID0gZW1haWxCcmFuZDtcbmNvbnN0IHsgbG9hZEJyYW5kQ29udGV4dCB9ID0gbm9kZUJyYW5kO1xuXG4vKipcbiAqIEJvb3QgdGhlIGdhdGUgYXBwIGFuZCByZXR1cm4gdGhlIEFQSSB0aGUgcHJveHkgY2FsbHMuIFRocm93cyB3aGVuIGVtYWlsIGlzIG5vdFxuICogaW4gU01UUCBtb2RlIChubyB3YXkgdG8gZGVsaXZlciBhIGNvZGUpIHNvIGEgbWlzY29uZmlndXJlZCBnYXRlIGZhaWxzIGZhc3QgYXRcbiAqIHN0YXJ0dXAgcmF0aGVyIHRoYW4gc2lsZW50bHkgYWNjZXB0aW5nIG5vYm9keTsgdGhlIGNhbGxlciBtYXkgY2F0Y2ggdGhpcyBhbmRcbiAqIGZhbGwgYmFjayB0byBpbnNlY3VyZS9vcGVuIG1vZGUgd2hlbiB0aGUgb3BlcmF0b3Igb3B0ZWQgaW4uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydEdhdGVBcHAoY29uZmlnOiBBdXRoR2F0ZUNvbmZpZyk6IFByb21pc2U8QXV0aEdhdGVBcGk+IHtcbiAgLy8gVGhlIGhvc3QgYXBwJ3Mgb3duIGJyYW5kIChgYnJhbmRpbmcvYnJhbmQueWFtbGAgZGlzY292ZXJlZCBmcm9tIGN3ZCkgb3IgdGhlXG4gIC8vIGRieC10b29scyBkZWZhdWx0LiBUaGlzIGlzIHRoZSBPTkUgYnJhbmQgc291cmNlIGZvciB0aGUgZ2F0ZTogaXQgc3R5bGVzIHRoZVxuICAvLyBjb2RlIGVtYWlsIChhY2NlbnQgYmFuZCwgZm9udCwgbG9nbykgdmlhIHRoZSBlbWFpbCBwbHVnaW4gQU5EIHN1cHBsaWVzIHRoZVxuICAvLyBkaXNwbGF5IG5hbWUgdGhlIGNvcHkgdXNlcywgc28gYSBkZXBsb3ltZW50IHRoYXQgdGhlbWVzIGl0cyBhcHAgdGhlbWVzIGl0c1xuICAvLyBzaWduLWluIGVtYWlsIHdpdGggaXQuIEFuIGV4cGxpY2l0IGBicmFuZE5hbWVgIHN0aWxsIHdpbnMgKHNlZSBiZWxvdykuXG4gIGNvbnN0IGNvbnRleHQgPSBhd2FpdCBsb2FkQnJhbmRDb250ZXh0KCk7XG5cbiAgLy8gYHNlbmRDb2RlYCBkZWxpdmVycyB0aGUgT1RQIHRocm91Z2ggdGhlIGVtYWlsIHBsdWdpbidzIFNIQVJFRCB0cmFuc3BvcnQsIHdoaWNoXG4gIC8vIHRoZSBgZW1haWwoKWAgcGx1Z2luIHByaW1lcyBkdXJpbmcgaXRzIGBzZXR1cCgpYCAoYXdhaXRlZCBieSBgY3JlYXRlQXBwYFxuICAvLyBiZWxvdykuIFVzaW5nIHRoZSBtb2R1bGUtbGV2ZWwgYHNlbmRFbWFpbGAgYXZvaWRzIGEgY2lyY3VsYXIgZGVwZW5kZW5jeSBvbiB0aGVcbiAgLy8gYXBwIGhhbmRsZSdzIGluZmVycmVkIHR5cGUuIFRoZSBgRnJvbWAgaXMgdGhlIFNZU1RFTSBzZW5kZXI6IGEgdmVyaWZpY2F0aW9uXG4gIC8vIGNvZGUgaXMgbWFjaGluZS1nZW5lcmF0ZWQgYW5kIHVuYW5zd2VyYWJsZSwgc28gaXQgbXVzdCBub3QgYXJyaXZlIGZyb20gYVxuICAvLyBwZXJzb24ncyBhZGRyZXNzIGludml0aW5nIGEgcmVwbHkuXG4gIGNvbnN0IHNlbmRDb2RlOiBOb25OdWxsYWJsZTxBdXRoR2F0ZUNvbmZpZ1tcInNlbmRDb2RlXCJdPiA9IGFzeW5jICh0bywgY29kZSwgb3B0cykgPT4ge1xuICAgIGNvbnN0IGZyb20gPSByZXNvbHZlU3lzdGVtU2VuZGVyQWRkcmVzcyhnZXRFbWFpbFJ1bnRpbWUoKS5jb25maWcpO1xuICAgIGF3YWl0IHNlbmRFbWFpbChcbiAgICAgIHtcbiAgICAgICAgdG86IFt0b10sXG4gICAgICAgIHN1YmplY3Q6IG9wdHMuc3ViamVjdCxcbiAgICAgICAgYm9keTogY29kZUVtYWlsSHRtbEJvZHkoY29kZSwgb3B0cyksXG4gICAgICB9LFxuICAgICAgZnJvbSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHsgdGV4dDogY29kZUVtYWlsVGV4dEJvZHkoY29kZSwgb3B0cykgfSxcbiAgICApO1xuICB9O1xuXG4gIC8vIGBjcmVhdGVBcHBgIG5hbWVzcGFjZXMgZWFjaCBwbHVnaW4ncyBleHBvcnRzIG9uIHRoZSBoYW5kbGUgYnkgbWFuaWZlc3QgbmFtZTtcbiAgLy8gYGhhbmRsZS5hdXRoR2F0ZWAgaXMgdGhlIGluLXByb2Nlc3MgZ2F0ZSBBUEkgdGhlIHByb3h5IGRyaXZlcy5cbiAgY29uc3QgaGFuZGxlID0gYXdhaXQgY3JlYXRlQXBwKHtcbiAgICBwbHVnaW5zOiBbXG4gICAgICAvLyBCcmFuZCB0aGUgY29kZSBlbWFpbCBmcm9tIHRoZSByZXNvbHZlZCBjb250ZXh0LCB0aGUgc2FtZSBicmlkZ2UgZXZlcnlcbiAgICAgIC8vIG90aGVyIGRieC10b29scyBlbWFpbCBzdXJmYWNlIHVzZXMgKGFjY2VudCArIGZvbnQgaW5saW5lZCwgbG9nbyBvbmx5IHdoZW5cbiAgICAgIC8vIGl0IGlzIGEgZmV0Y2hhYmxlIFVSTCAtIGEgcGFja2FnZS1leHBvcnQgcGF0aCBjYW5ub3QgbG9hZCBpbiBhbiBpbmJveCkuXG4gICAgICBlbWFpbCh7IGJyYW5kOiBlbWFpbEJyYW5kRnJvbUNvbnRleHQoY29udGV4dCkgfSksXG4gICAgICAvLyBgYnJhbmROYW1lYCBmYWxscyBiYWNrIHRvIHRoZSByZXNvbHZlZCBjb250ZXh0J3MgZGlzcGxheSBuYW1lLCBzbyB0aGVcbiAgICAgIC8vIGVtYWlsIGNvcHkgbmFtZXMgdGhlIGFwcCByYXRoZXIgdGhhbiBhIGdlbmVyaWMgcGxhY2Vob2xkZXIuIFNwZWxsZWQgYXMgYW5cbiAgICAgIC8vIGV4cGxpY2l0IGA/P2AgcmF0aGVyIHRoYW4gYSBrZXkgYmVmb3JlIGAuLi5jb25maWdgOiBjb21tYW5kZXIgc2V0c1xuICAgICAgLy8gYGJyYW5kTmFtZWAgb24gdGhlIG9wdGlvbnMgb2JqZWN0IHdoZXRoZXIgb3Igbm90IHRoZSBmbGFnIHdhcyBwYXNzZWQsIHNvXG4gICAgICAvLyBzcHJlYWRpbmcgaXQgd291bGQgY2xvYmJlciB0aGUgY29udGV4dCBuYW1lIHdpdGggYHVuZGVmaW5lZGAuXG4gICAgICBhdXRoR2F0ZSh7IC4uLmNvbmZpZywgYnJhbmROYW1lOiBjb25maWcuYnJhbmROYW1lID8/IGNvbnRleHQubmFtZSwgc2VuZENvZGUgfSksXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gRmFpbCBmYXN0OiB0aGUgZ2F0ZSBuZWVkcyBTTVRQIHRvIGVtYWlsIGNvZGVzLiBgZ2V0RW1haWxSdW50aW1lKClgIHJlc29sdmVzIHRvXG4gIC8vIGBtb2RlOiBcImZpbGVcImAgKG91dGJveCkgb3IgdGhyb3dzIHdoZW4gbm8gU01UUCBjcmVkcyBhcmUgY29uZmlndXJlZCAtIG5laXRoZXJcbiAgLy8gY2FuIGRlbGl2ZXIgdG8gYSByZWFsIGluYm94LCBzbyByZWZ1c2UgdG8gYnJpbmcgdXAgYSBnYXRlIHRoYXQgbGV0cyBub2JvZHkgaW4uXG4gIGlmIChnZXRFbWFpbFJ1bnRpbWUoKS5jb25maWcubW9kZSAhPT0gXCJzbXRwXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBcImVtYWlsIGlzIG5vdCBjb25maWd1cmVkIGZvciBTTVRQIGRlbGl2ZXJ5IC0gdGhlIE9UUCBnYXRlIGNhbm5vdCBzZW5kIGNvZGVzLiBcIiArXG4gICAgICAgIFwiU2V0IFNNVFBfSE9TVC9TTVRQX1VTRVIvU01UUF9QQVNTV09SRCwgb3IgcGFzcyAtLWluc2VjdXJlIC8gVFVOTkVMX0lOU0VDVVJFPXRydWUgdG8gcnVuIHRoZSB0dW5uZWwgb3Blbi5cIixcbiAgICApO1xuICB9XG5cbiAgbG9nZ2VyLmluZm8oXCJnYXRlIGFwcCByZWFkeSAobm8gc2VydmVyOyBwcm94eS1kcml2ZW4pXCIpO1xuICByZXR1cm4gaGFuZGxlLmF1dGhHYXRlIGFzIEF1dGhHYXRlQXBpO1xufVxuIl19
|
package/package.json
CHANGED
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@clack/prompts": "^1.7.0",
|
|
31
31
|
"@databricks/appkit": "^0.43.0",
|
|
32
|
-
"@dbx-tools/appkit": "0.6.
|
|
33
|
-
"@dbx-tools/core": "0.6.
|
|
34
|
-
"@dbx-tools/email": "0.6.
|
|
35
|
-
"@dbx-tools/shared-core": "0.6.
|
|
36
|
-
"@dbx-tools/shared-email": "0.6.
|
|
32
|
+
"@dbx-tools/appkit": "0.6.55",
|
|
33
|
+
"@dbx-tools/core": "0.6.55",
|
|
34
|
+
"@dbx-tools/email": "0.6.55",
|
|
35
|
+
"@dbx-tools/shared-core": "0.6.55",
|
|
36
|
+
"@dbx-tools/shared-email": "0.6.55",
|
|
37
37
|
"commander": "^15.0.0",
|
|
38
38
|
"http-proxy-3": "^1.23.3",
|
|
39
39
|
"jose": "^6.2.3"
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"./package.json": "./package.json"
|
|
101
101
|
}
|
|
102
102
|
},
|
|
103
|
-
"version": "0.6.
|
|
103
|
+
"version": "0.6.55",
|
|
104
104
|
"types": "./lib/index.d.ts",
|
|
105
105
|
"type": "module",
|
|
106
106
|
"exports": {
|
package/src/app.ts
CHANGED
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
*
|
|
12
12
|
* It returns the {@link AuthGateApi} the proxy drives. `sendCode` is wired here
|
|
13
13
|
* (the plugin can't resolve HOW to send on its own) to the email plugin's
|
|
14
|
-
* transport
|
|
15
|
-
*
|
|
14
|
+
* transport. A sign-in code is SYSTEM mail - no on-behalf-of user asked for it
|
|
15
|
+
* and no reply to it reaches anyone - so it sends from the email config's
|
|
16
|
+
* do-not-reply address (`no-reply@EMAIL_DOMAIN` unless EMAIL_SYSTEM_FROM names
|
|
17
|
+
* another).
|
|
16
18
|
*
|
|
17
19
|
* FAIL FAST: a gate that can't email a code is useless, so if email does not
|
|
18
20
|
* resolve to SMTP mode (real delivery), this throws - unless `insecure` is set
|
|
@@ -26,7 +28,7 @@ import { createApp as createAppNs } from "@dbx-tools/appkit";
|
|
|
26
28
|
import { brand as nodeBrand } from "@dbx-tools/core";
|
|
27
29
|
import { brand as emailBrand, email, sender, transport } from "@dbx-tools/email";
|
|
28
30
|
import { log, string } from "@dbx-tools/shared-core";
|
|
29
|
-
import { authGate, type AuthGateApi, type AuthGateConfig } from "./plugin.ts";
|
|
31
|
+
import { authGate, type AuthGateApi, type AuthGateConfig, type SendCodeOptions } from "./plugin.ts";
|
|
30
32
|
|
|
31
33
|
const logger = log.logger("tunnel:app");
|
|
32
34
|
|
|
@@ -43,8 +45,58 @@ export function expiresIn(seconds: number): string {
|
|
|
43
45
|
: string.pluralize(seconds, "second");
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
/** The parts of {@link SendCodeOptions} the code email's copy is built from. */
|
|
49
|
+
type CodeCopy = Pick<SendCodeOptions, "message" | "codeTtlSeconds">;
|
|
50
|
+
|
|
51
|
+
/** The reassurance line closing both parts. */
|
|
52
|
+
const IGNORE_LINE = "If you did not request this code, you can ignore this email.";
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The HTML part's source: the full branded template, with the code as a large
|
|
56
|
+
* styled heading (`## ` is what makes it prominent in an inbox).
|
|
57
|
+
*/
|
|
58
|
+
export function codeEmailHtmlBody(code: string, opts: CodeCopy): string {
|
|
59
|
+
return [
|
|
60
|
+
opts.message,
|
|
61
|
+
"",
|
|
62
|
+
`## ${code}`,
|
|
63
|
+
"",
|
|
64
|
+
`This code expires in ${expiresIn(opts.codeTtlSeconds)}.`,
|
|
65
|
+
"",
|
|
66
|
+
IGNORE_LINE,
|
|
67
|
+
].join("\n");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The `text/plain` part, supplied EXPLICITLY rather than rendered from the tree
|
|
72
|
+
* above. Both parts say the same thing; only the line layout differs.
|
|
73
|
+
*
|
|
74
|
+
* The prompt and the code share ONE line ("Your verification code is: 123456").
|
|
75
|
+
* That single-line shape is what iOS, Gmail, Outlook, and Android code detection
|
|
76
|
+
* keys on most reliably - the heuristics look for a code in the same sentence as
|
|
77
|
+
* a recognized prompt, so splitting them across lines makes detection dependent
|
|
78
|
+
* on the client, and any blank line between them defeats it outright.
|
|
79
|
+
*
|
|
80
|
+
* The GENERATED text part cannot hold that shape at all: it is a rendering of the
|
|
81
|
+
* HTML, so it carries the brand header/footer and turns the code heading's CSS
|
|
82
|
+
* margin into blank lines, arriving as `prompt\n\n\ncode`.
|
|
83
|
+
*
|
|
84
|
+
* The code is visible text in BOTH parts, never an image, so a client scraping
|
|
85
|
+
* either one finds it. No trailer line follows the copy - Apple's domain-bound
|
|
86
|
+
* `@domain #code` footer is deliberately NOT emitted, since it constrains the
|
|
87
|
+
* code to one origin and is not what the broadly-compatible shape needs.
|
|
88
|
+
*/
|
|
89
|
+
export function codeEmailTextBody(code: string, opts: CodeCopy): string {
|
|
90
|
+
return [
|
|
91
|
+
`${opts.message} ${code}`,
|
|
92
|
+
`This code expires in ${expiresIn(opts.codeTtlSeconds)}.`,
|
|
93
|
+
"",
|
|
94
|
+
IGNORE_LINE,
|
|
95
|
+
].join("\n");
|
|
96
|
+
}
|
|
97
|
+
|
|
46
98
|
const { createApp } = createAppNs;
|
|
47
|
-
const {
|
|
99
|
+
const { resolveSystemSenderAddress } = sender;
|
|
48
100
|
const { getEmailRuntime, sendEmail } = transport;
|
|
49
101
|
const { emailBrandFromContext } = emailBrand;
|
|
50
102
|
const { loadBrandContext } = nodeBrand;
|
|
@@ -66,32 +118,20 @@ export async function startGateApp(config: AuthGateConfig): Promise<AuthGateApi>
|
|
|
66
118
|
// `sendCode` delivers the OTP through the email plugin's SHARED transport, which
|
|
67
119
|
// the `email()` plugin primes during its `setup()` (awaited by `createApp`
|
|
68
120
|
// below). Using the module-level `sendEmail` avoids a circular dependency on the
|
|
69
|
-
// app handle's inferred type. `From` is the
|
|
70
|
-
//
|
|
121
|
+
// app handle's inferred type. The `From` is the SYSTEM sender: a verification
|
|
122
|
+
// code is machine-generated and unanswerable, so it must not arrive from a
|
|
123
|
+
// person's address inviting a reply.
|
|
71
124
|
const sendCode: NonNullable<AuthGateConfig["sendCode"]> = async (to, code, opts) => {
|
|
72
|
-
const from =
|
|
125
|
+
const from = resolveSystemSenderAddress(getEmailRuntime().config);
|
|
73
126
|
await sendEmail(
|
|
74
127
|
{
|
|
75
128
|
to: [to],
|
|
76
129
|
subject: opts.subject,
|
|
77
|
-
|
|
78
|
-
// then the bare code ALONE on the next line, then the expiry. iOS, Gmail,
|
|
79
|
-
// Outlook, and Android all detect a code from this shape and offer to
|
|
80
|
-
// autofill it, and anything more decorative is what breaks that. The code
|
|
81
|
-
// stays visible TEXT in both MIME parts (the email plugin renders the
|
|
82
|
-
// HTML and plain-text alternatives from one React Email tree), never an
|
|
83
|
-
// image, so a client that scrapes the text part still finds it.
|
|
84
|
-
body: [
|
|
85
|
-
opts.message,
|
|
86
|
-
"",
|
|
87
|
-
`## ${code}`,
|
|
88
|
-
"",
|
|
89
|
-
`This code expires in ${expiresIn(opts.codeTtlSeconds)}.`,
|
|
90
|
-
"",
|
|
91
|
-
"If you did not request this code, you can ignore this email.",
|
|
92
|
-
].join("\n"),
|
|
130
|
+
body: codeEmailHtmlBody(code, opts),
|
|
93
131
|
},
|
|
94
132
|
from,
|
|
133
|
+
undefined,
|
|
134
|
+
{ text: codeEmailTextBody(code, opts) },
|
|
95
135
|
);
|
|
96
136
|
};
|
|
97
137
|
|