@envseal/prompters 0.1.1 → 0.1.3

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/dist/ide.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { PromptRequest, PromptResponse } from './types.js';
2
2
  export declare class IdePrompter {
3
- readonly id: 'ide';
3
+ readonly id: "ide";
4
4
  available(): Promise<boolean>;
5
5
  cancel(ticket: string): Promise<void>;
6
6
  prompt(req: PromptRequest): Promise<PromptResponse>;
@@ -12,7 +12,7 @@ export interface LoopbackPrompterOptions {
12
12
  }) => void;
13
13
  }
14
14
  export declare class LoopbackPrompter implements Prompter {
15
- readonly id: 'loopback-browser';
15
+ readonly id: "loopback-browser";
16
16
  private readonly options;
17
17
  private openerProbe;
18
18
  private current;
package/dist/loopback.js CHANGED
@@ -44,17 +44,29 @@ function respondText(res, status, body, headers) {
44
44
  function renderKeySection(key) {
45
45
  const sectionId = `field-${key.key}`;
46
46
  const revealId = `reveal-${key.key}`;
47
+ // Audit follow-up: these links are manifest/model-controlled. Rendering a
48
+ // polished "Get your key" button with no destination shown turned the
49
+ // consent page itself into a phishing referral inside trusted envseal
50
+ // chrome. The hostname is now part of the visible link text, so wherever
51
+ // the user would land is on screen before they click.
52
+ const externalLink = (cls, url, label) => {
53
+ let host;
54
+ try {
55
+ host = new URL(url).hostname;
56
+ }
57
+ catch {
58
+ return ''; // unreachable when isHttpUrl gates the call; fail closed anyway
59
+ }
60
+ return (` <p class="${cls}"><a href="${escapeHtml(url)}" ` +
61
+ `rel="noreferrer noopener" target="_blank">${escapeHtml(label)} \u2192 ${escapeHtml(host)}</a></p>\n`);
62
+ };
47
63
  let signup = '';
48
64
  if (isHttpUrl(key.signupUrl ?? '')) {
49
- signup =
50
- ` <p class="signup"><a href="${escapeHtml(key.signupUrl ?? '')}" ` +
51
- `rel="noreferrer noopener" target="_blank">Get your key</a></p>\n`;
65
+ signup = externalLink('signup', key.signupUrl ?? '', 'Get your key');
52
66
  }
53
67
  let docs = '';
54
68
  if (isHttpUrl(key.docsUrl ?? '')) {
55
- docs =
56
- ` <p class="docs"><a href="${escapeHtml(key.docsUrl ?? '')}" ` +
57
- `rel="noreferrer noopener" target="_blank">Documentation</a></p>\n`;
69
+ docs = externalLink('docs', key.docsUrl ?? '', 'Documentation');
58
70
  }
59
71
  let hint = '';
60
72
  if (key.formatHint) {
@@ -230,7 +242,7 @@ export class LoopbackPrompter {
230
242
  const promptPromise = new Promise((resolve) => {
231
243
  resolvePrompt = resolve;
232
244
  });
233
- let launchedUrl;
245
+ const state = {};
234
246
  let complete = () => { };
235
247
  let teardown = () => { };
236
248
  const sockets = new Set();
@@ -262,8 +274,8 @@ export class LoopbackPrompter {
262
274
  settled = true;
263
275
  clearTimeout(timer);
264
276
  teardown();
265
- if (launchedUrl !== undefined) {
266
- resolvePrompt({ ticket: req.ticket, results, url: launchedUrl });
277
+ if (state.launchedUrl !== undefined) {
278
+ resolvePrompt({ ticket: req.ticket, results, url: state.launchedUrl });
267
279
  }
268
280
  else {
269
281
  resolvePrompt({ ticket: req.ticket, results });
@@ -299,7 +311,8 @@ export class LoopbackPrompter {
299
311
  const launched = this.options.openBrowser === false
300
312
  ? { ok: false, url: fallbackUrl }
301
313
  : await openBrowser(address.port, pathNonce);
302
- launchedUrl = launched.ok ? undefined : launched.url;
314
+ if (!launched.ok)
315
+ state.launchedUrl = launched.url;
303
316
  const result = await promptPromise;
304
317
  if (this.current !== null && this.current.ticket === req.ticket) {
305
318
  this.current = null;
package/dist/native.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { Prompter, PromptRequest, PromptResponse } from './types.js';
2
2
  export declare class NativePrompter implements Prompter {
3
- readonly id: 'native-dialog';
3
+ readonly id: "native-dialog";
4
4
  private adapter;
5
5
  available(): Promise<boolean>;
6
6
  cancel(_ticket: string): Promise<void>;
package/dist/none.d.ts CHANGED
@@ -4,7 +4,7 @@ import type { Prompter, PromptRequest, PromptResponse } from './types.js';
4
4
  * MUST NOT fall back to asking in chat.
5
5
  */
6
6
  export declare class NonePrompter implements Prompter {
7
- readonly id: 'none';
7
+ readonly id: "none";
8
8
  available(): Promise<boolean>;
9
9
  cancel(_ticket: string): Promise<void>;
10
10
  prompt(req: PromptRequest): Promise<PromptResponse>;
package/dist/tty.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { Prompter, PromptRequest, PromptResponse } from './types.js';
2
2
  export declare class TtyPrompter implements Prompter {
3
- readonly id: 'tty';
3
+ readonly id: "tty";
4
4
  available(): Promise<boolean>;
5
5
  private openReadFd;
6
6
  private openWriteFd;
package/dist/tty.js CHANGED
@@ -8,7 +8,6 @@ import { asSecret } from '@envseal/protocol';
8
8
  const POSIX_DEVICE = '/dev/tty';
9
9
  const WIN_IN = 'CONIN$';
10
10
  const WIN_OUT = 'CONOUT$';
11
- const ENABLE_ECHO_INPUT = 0x4;
12
11
  function isPosix() {
13
12
  return process.platform !== 'win32';
14
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@envseal/prompters",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "provenance": true
21
21
  },
22
22
  "dependencies": {
23
- "@envseal/protocol": "0.1.1"
23
+ "@envseal/protocol": "0.1.3"
24
24
  },
25
25
  "devDependencies": {
26
26
  "undici": "^7.2.0"