@rndmjoker/proton-mcp 0.4.13 → 0.5.1

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.
Files changed (95) hide show
  1. package/README.md +138 -21
  2. package/dist/browser/channel.d.ts +76 -0
  3. package/dist/browser/channel.js +162 -0
  4. package/dist/browser/channel.js.map +1 -0
  5. package/dist/browser/client.d.ts +50 -0
  6. package/dist/browser/client.js +284 -0
  7. package/dist/browser/client.js.map +1 -0
  8. package/dist/browser/connector.d.ts +15 -0
  9. package/dist/browser/connector.js +26 -0
  10. package/dist/browser/connector.js.map +1 -0
  11. package/dist/browser/host.d.ts +50 -0
  12. package/dist/browser/host.js +258 -0
  13. package/dist/browser/host.js.map +1 -0
  14. package/dist/browser/messages.d.ts +163 -0
  15. package/dist/browser/messages.js +338 -0
  16. package/dist/browser/messages.js.map +1 -0
  17. package/dist/browser/paths.d.ts +51 -0
  18. package/dist/browser/paths.js +92 -0
  19. package/dist/browser/paths.js.map +1 -0
  20. package/dist/browser/setup.d.ts +42 -0
  21. package/dist/browser/setup.js +170 -0
  22. package/dist/browser/setup.js.map +1 -0
  23. package/dist/filters/order.d.ts +66 -0
  24. package/dist/filters/order.js +108 -0
  25. package/dist/filters/order.js.map +1 -0
  26. package/dist/filters/sieve.d.ts +184 -0
  27. package/dist/filters/sieve.js +1312 -0
  28. package/dist/filters/sieve.js.map +1 -0
  29. package/dist/instances.d.ts +58 -0
  30. package/dist/instances.js +145 -0
  31. package/dist/instances.js.map +1 -0
  32. package/dist/mail/compose.d.ts +10 -0
  33. package/dist/mail/compose.js.map +1 -1
  34. package/dist/mail/record.d.ts +36 -0
  35. package/dist/mail/record.js +74 -0
  36. package/dist/mail/record.js.map +1 -0
  37. package/dist/permissions.d.ts +139 -0
  38. package/dist/permissions.js +355 -0
  39. package/dist/permissions.js.map +1 -0
  40. package/dist/server.js +330 -16
  41. package/dist/server.js.map +1 -1
  42. package/dist/session.d.ts +12 -0
  43. package/dist/session.js +23 -0
  44. package/dist/session.js.map +1 -1
  45. package/dist/settings.d.ts +81 -11
  46. package/dist/settings.js +160 -25
  47. package/dist/settings.js.map +1 -1
  48. package/dist/tools/confirm.d.ts +4 -2
  49. package/dist/tools/confirm.js +12 -3
  50. package/dist/tools/confirm.js.map +1 -1
  51. package/dist/tools/failures.d.ts +6 -8
  52. package/dist/tools/failures.js +36 -17
  53. package/dist/tools/failures.js.map +1 -1
  54. package/dist/tools/filter-tools.d.ts +82 -0
  55. package/dist/tools/filter-tools.js +729 -0
  56. package/dist/tools/filter-tools.js.map +1 -0
  57. package/dist/tools/filters.d.ts +8 -1
  58. package/dist/tools/filters.js +24 -12
  59. package/dist/tools/filters.js.map +1 -1
  60. package/dist/tools/format.d.ts +15 -0
  61. package/dist/tools/format.js +4 -3
  62. package/dist/tools/format.js.map +1 -1
  63. package/dist/tools/guidance.js +12 -7
  64. package/dist/tools/guidance.js.map +1 -1
  65. package/dist/tools/interface.d.ts +20 -6
  66. package/dist/tools/interface.js +40 -16
  67. package/dist/tools/interface.js.map +1 -1
  68. package/dist/tools/send.d.ts +9 -0
  69. package/dist/tools/send.js +51 -9
  70. package/dist/tools/send.js.map +1 -1
  71. package/dist/tools/sign-in-required.d.ts +15 -2
  72. package/dist/tools/sign-in-required.js +30 -2
  73. package/dist/tools/sign-in-required.js.map +1 -1
  74. package/dist/web/layout.d.ts +12 -5
  75. package/dist/web/layout.js +32 -9
  76. package/dist/web/layout.js.map +1 -1
  77. package/dist/web/pages.d.ts +4 -2
  78. package/dist/web/pages.js +10 -9
  79. package/dist/web/pages.js.map +1 -1
  80. package/dist/web/pending.d.ts +9 -6
  81. package/dist/web/pending.js +9 -7
  82. package/dist/web/pending.js.map +1 -1
  83. package/dist/web/preview-server.d.ts +33 -0
  84. package/dist/web/preview-server.js +102 -0
  85. package/dist/web/preview-server.js.map +1 -0
  86. package/dist/web/sections.d.ts +86 -1
  87. package/dist/web/sections.js +290 -7
  88. package/dist/web/sections.js.map +1 -1
  89. package/dist/web/security.d.ts +48 -13
  90. package/dist/web/security.js +68 -16
  91. package/dist/web/security.js.map +1 -1
  92. package/dist/web/server.d.ts +81 -24
  93. package/dist/web/server.js +478 -117
  94. package/dist/web/server.js.map +1 -1
  95. package/package.json +1 -1
@@ -0,0 +1,258 @@
1
+ /**
2
+ * The connector Chrome starts for the extension (#59), in Chrome's words a
3
+ * native messaging host.
4
+ *
5
+ * Chrome starts it when the extension asks for it, hands it the extension's
6
+ * origin as the first argument, and talks to it over standard input and
7
+ * output. Chrome starts it only for the extension named in its manifest, and
8
+ * only from that extension: a web page cannot reach it.
9
+ *
10
+ * The connector opens a socket file for this server and relays between the two.
11
+ * It holds nothing and decides nothing about filters. What it does decide is
12
+ * who gets through:
13
+ *
14
+ * - Chrome's origin has to be the extension's fixed id.
15
+ * - A connection on the socket has to prove it knows the secret from the
16
+ * setup before it may send anything, and the connector proves the same back.
17
+ * - Every request has to be one of the three kinds in messages.ts, in exactly
18
+ * that shape, and every answer from the extension as well.
19
+ *
20
+ * It stops when Chrome closes the channel, which happens when the extension
21
+ * is switched off, reloaded or removed, or when Chrome quits.
22
+ *
23
+ * The setup copies this file, with connector.ts, paths.ts, channel.ts and
24
+ * messages.ts, into the user's configuration directory, and connector.ts
25
+ * starts it with the Node the setup ran under. So it imports nothing but Node
26
+ * and those files.
27
+ */
28
+ import { createServer, connect } from 'node:net';
29
+ import { existsSync, unlinkSync, chmodSync } from 'node:fs';
30
+ import { dirname } from 'node:path';
31
+ import { EXTENSION_ID, PROTOCOL_VERSION, parseRequest, parseResponse, isRequestId } from './messages.js';
32
+ import { encodeNative, NativeReader, LineReader, MAX_REQUEST_LINE, parseLine, newNonce, proof, proofMatches, isNonce, readSecret, ensurePrivateDir, } from './channel.js';
33
+ /** How long a request may wait for the extension. Filling in a confirmation is not waited for. */
34
+ export const REQUEST_TIMEOUT_MS = 60_000;
35
+ /** How long a new connection has to prove the secret. */
36
+ const AUTH_TIMEOUT_MS = 3_000;
37
+ const MAX_PENDING_PER_CONNECTION = 4;
38
+ const MAX_PENDING = 16;
39
+ /** True when something already answers on the socket: a connector of another Chrome profile. */
40
+ function answers(path) {
41
+ return new Promise((resolve) => {
42
+ const probe = connect(path);
43
+ const timer = setTimeout(() => {
44
+ probe.destroy();
45
+ resolve(false);
46
+ }, 500);
47
+ probe.once('connect', () => {
48
+ clearTimeout(timer);
49
+ probe.destroy();
50
+ resolve(true);
51
+ });
52
+ probe.once('error', () => {
53
+ clearTimeout(timer);
54
+ resolve(false);
55
+ });
56
+ });
57
+ }
58
+ export async function runHost(options) {
59
+ const { input, output, paths } = options;
60
+ const log = options.log ?? (() => undefined);
61
+ const timeoutMs = options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
62
+ const isPipe = paths.platform === 'win32';
63
+ const toChrome = (message) => new Promise((resolve) => {
64
+ try {
65
+ output.write(encodeNative(message), () => resolve());
66
+ }
67
+ catch (error) {
68
+ log(`could not pass a message to Chrome: ${error.message}`);
69
+ resolve();
70
+ }
71
+ });
72
+ // Reported to the extension, which shows it in its popup, and then the
73
+ // connector ends: Chrome sees the channel close and the extension knows why.
74
+ const giveUp = async (failure) => {
75
+ log(failure);
76
+ await toChrome({ type: 'host-error', message: failure });
77
+ return { done: Promise.resolve(), failure, close: async () => undefined };
78
+ };
79
+ if (options.origin !== `chrome-extension://${EXTENSION_ID}/`) {
80
+ return giveUp('The connector was started for an extension it does not serve.');
81
+ }
82
+ const secret = readSecret(paths.secretFile);
83
+ if (!secret) {
84
+ return giveUp('The connector is not set up: the secret is missing. Run the setup again.');
85
+ }
86
+ if (!isPipe) {
87
+ try {
88
+ ensurePrivateDir(dirname(paths.socket));
89
+ }
90
+ catch (error) {
91
+ return giveUp(error.message);
92
+ }
93
+ }
94
+ if ((isPipe || existsSync(paths.socket)) && (await answers(paths.socket))) {
95
+ return giveUp('Another Chrome profile already runs the connector. Only one profile at a time can serve the server; ' +
96
+ 'switch the extension off in the other one.');
97
+ }
98
+ if (!isPipe && existsSync(paths.socket)) {
99
+ // Left behind by a connector that did not get to clean up.
100
+ try {
101
+ unlinkSync(paths.socket);
102
+ }
103
+ catch {
104
+ // Listening fails below with the reason.
105
+ }
106
+ }
107
+ const pending = new Map();
108
+ const sockets = new Set();
109
+ let counter = 0;
110
+ const server = createServer((socket) => serve(socket));
111
+ try {
112
+ await new Promise((resolve, reject) => {
113
+ server.once('error', reject);
114
+ server.listen(paths.socket, () => {
115
+ server.off('error', reject);
116
+ resolve();
117
+ });
118
+ });
119
+ }
120
+ catch (error) {
121
+ return giveUp(`The connector could not open its socket: ${error.message}`);
122
+ }
123
+ if (!isPipe)
124
+ chmodSync(paths.socket, 0o600);
125
+ await toChrome({ type: 'host-ready', version: PROTOCOL_VERSION });
126
+ function serve(socket) {
127
+ sockets.add(socket);
128
+ const reader = new LineReader(MAX_REQUEST_LINE);
129
+ const nonce = newNonce();
130
+ let ready = false;
131
+ const send = (message) => {
132
+ if (!socket.destroyed)
133
+ socket.write(`${JSON.stringify(message)}\n`);
134
+ };
135
+ const answer = (clientId, body) => send({ type: 'response', id: clientId, body });
136
+ const authTimer = setTimeout(() => socket.destroy(), AUTH_TIMEOUT_MS);
137
+ send({ type: 'hello', version: PROTOCOL_VERSION, nonce });
138
+ socket.on('data', (chunk) => {
139
+ let lines;
140
+ try {
141
+ lines = reader.push(chunk);
142
+ }
143
+ catch {
144
+ socket.destroy();
145
+ return;
146
+ }
147
+ for (const line of lines) {
148
+ const message = parseLine(line);
149
+ if (!ready) {
150
+ clearTimeout(authTimer);
151
+ if (!message ||
152
+ message.type !== 'auth' ||
153
+ !isNonce(message.nonce) ||
154
+ !proofMatches(secret, 'client', nonce, message.proof)) {
155
+ log('refused a connection that could not prove the secret');
156
+ socket.destroy();
157
+ return;
158
+ }
159
+ ready = true;
160
+ send({ type: 'ready', proof: proof(secret, 'host', message.nonce) });
161
+ continue;
162
+ }
163
+ if (!message || message.type !== 'request' || !isRequestId(message.id)) {
164
+ socket.destroy();
165
+ return;
166
+ }
167
+ const clientId = message.id;
168
+ const body = parseRequest(message.body);
169
+ if (!body) {
170
+ answer(clientId, { ok: false, error: 'unknown-request', message: 'The connector does not pass on this request.' });
171
+ continue;
172
+ }
173
+ const mine = [...pending.values()].filter((entry) => entry.socket === socket).length;
174
+ if (mine >= MAX_PENDING_PER_CONNECTION || pending.size >= MAX_PENDING) {
175
+ answer(clientId, { ok: false, error: 'busy', message: 'The extension is still working on earlier requests.' });
176
+ continue;
177
+ }
178
+ const id = `h${++counter}`;
179
+ const timer = setTimeout(() => {
180
+ pending.delete(id);
181
+ answer(clientId, { ok: false, error: 'timeout', message: 'The extension did not answer in time.' });
182
+ }, timeoutMs);
183
+ pending.set(id, { socket, clientId, timer });
184
+ void toChrome({ type: 'request', id, body });
185
+ }
186
+ });
187
+ socket.on('close', () => {
188
+ clearTimeout(authTimer);
189
+ sockets.delete(socket);
190
+ for (const [id, entry] of pending) {
191
+ if (entry.socket === socket) {
192
+ clearTimeout(entry.timer);
193
+ pending.delete(id);
194
+ }
195
+ }
196
+ });
197
+ socket.on('error', () => undefined);
198
+ }
199
+ const native = new NativeReader();
200
+ input.on('data', (chunk) => {
201
+ let messages;
202
+ try {
203
+ messages = native.push(chunk);
204
+ }
205
+ catch (error) {
206
+ log(error.message);
207
+ void close();
208
+ return;
209
+ }
210
+ for (const message of messages) {
211
+ if (typeof message !== 'object' || message === null)
212
+ continue;
213
+ const { type, id, body } = message;
214
+ if (type !== 'response' || typeof id !== 'string')
215
+ continue;
216
+ const entry = pending.get(id);
217
+ if (!entry)
218
+ continue;
219
+ pending.delete(id);
220
+ clearTimeout(entry.timer);
221
+ const parsed = parseResponse(body) ?? {
222
+ ok: false,
223
+ error: 'internal',
224
+ message: 'The extension answered in a shape the connector does not pass on.',
225
+ };
226
+ if (!entry.socket.destroyed) {
227
+ entry.socket.write(`${JSON.stringify({ type: 'response', id: entry.clientId, body: parsed })}\n`);
228
+ }
229
+ }
230
+ });
231
+ let resolveDone;
232
+ const done = new Promise((resolve) => (resolveDone = resolve));
233
+ let closing;
234
+ function close() {
235
+ closing ??= (async () => {
236
+ for (const entry of pending.values())
237
+ clearTimeout(entry.timer);
238
+ pending.clear();
239
+ for (const socket of sockets)
240
+ socket.destroy();
241
+ await new Promise((resolve) => server.close(() => resolve()));
242
+ if (!isPipe) {
243
+ try {
244
+ unlinkSync(paths.socket);
245
+ }
246
+ catch {
247
+ // Already gone.
248
+ }
249
+ }
250
+ resolveDone();
251
+ })();
252
+ return closing;
253
+ }
254
+ input.on('end', () => void close());
255
+ input.on('close', () => void close());
256
+ return { done, close };
257
+ }
258
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/browser/host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * What the server, the connector and the browser extension may say to each other
3
+ * (#59).
4
+ *
5
+ * Three programs pass messages along: this server asks, the connector Chrome
6
+ * starts relays, and the extension does the work in the signed-in Proton page.
7
+ * Each of them checks every message against the fixed list below and drops
8
+ * anything else, so a program that reaches one of the channels can ask for
9
+ * nothing beyond these seven things. Unknown fields are refused rather than
10
+ * ignored: a field nobody reads today is one somebody may read tomorrow.
11
+ *
12
+ * The limits here are about shape, not about what is allowed. Whether a script
13
+ * may be saved is decided by src/filters/sieve.ts, in this server and again in
14
+ * the extension.
15
+ *
16
+ * Nothing from Node in here: the extension imports this file as well.
17
+ */
18
+ /** The name Chrome knows the connector by. It has to match the host manifest. */
19
+ export declare const HOST_NAME = "com.rndmjoker.proton_mcp";
20
+ /**
21
+ * The id of the extension, fixed by the public key in its manifest.
22
+ *
23
+ * Chrome starts the connector only for the extensions its manifest names, and
24
+ * the connector checks the origin Chrome hands it once more.
25
+ */
26
+ export declare const EXTENSION_ID = "nfmconelbflppeoolebhcckbmffiokkd";
27
+ /** Raised whenever a message changes shape, so an old connector and a new server notice each other. */
28
+ export declare const PROTOCOL_VERSION = 1;
29
+ export interface FilterProposal {
30
+ name: string;
31
+ sieve: string;
32
+ /** The id of the filter this one replaces. Absent for a new filter. */
33
+ replaces?: string;
34
+ /**
35
+ * Whether to apply it to the mail already there once it is saved. With a
36
+ * question, this only ticks the box in the window, and the user decides.
37
+ */
38
+ apply?: boolean;
39
+ }
40
+ /** One move of a filter in Proton's order: the filter and the position it ends up at, from 1. */
41
+ export interface FilterMoveRequest {
42
+ id: string;
43
+ position: number;
44
+ }
45
+ export type BrowserRequest = {
46
+ kind: 'status';
47
+ } | {
48
+ kind: 'list_filters';
49
+ account: string;
50
+ } | {
51
+ kind: 'propose_filter';
52
+ account: string;
53
+ proposal: FilterProposal;
54
+ confirm: boolean;
55
+ /** Whether applying to the mail already there may be offered at all: apply_filter is not switched off. */
56
+ applyAllowed: boolean;
57
+ } | {
58
+ kind: 'apply_filter';
59
+ account: string;
60
+ filterId: string;
61
+ confirm: boolean;
62
+ } | {
63
+ kind: 'reorder_filters';
64
+ account: string;
65
+ moves: FilterMoveRequest[];
66
+ confirm: boolean;
67
+ } | {
68
+ kind: 'delete_filter';
69
+ account: string;
70
+ filterId: string;
71
+ confirm: boolean;
72
+ } | {
73
+ kind: 'set_filter_status';
74
+ account: string;
75
+ filterId: string;
76
+ enabled: boolean;
77
+ confirm: boolean;
78
+ };
79
+ export interface ProtonFilter {
80
+ id: string;
81
+ name: string;
82
+ enabled: boolean;
83
+ /** Proton runs filters in this order, lowest first. */
84
+ order: number;
85
+ version: number;
86
+ sieve: string;
87
+ }
88
+ export type BrowserErrorCode = 'no-proton-tab' | 'signed-out' | 'wrong-account' | 'refused' | 'proton-error' | 'app-version' | 'not-found' | 'busy' | 'timeout' | 'internal' | 'unknown-request';
89
+ /** An action waiting in the extension's queue because Proton was busy with an earlier one. */
90
+ export interface QueuedAction {
91
+ action: 'save' | 'apply' | 'reorder' | 'delete' | 'status';
92
+ name: string;
93
+ /** When it was queued, in milliseconds since 1970. */
94
+ since: number;
95
+ attempts: number;
96
+ }
97
+ /** A change the extension made or was asked to make, as its popup lists them. */
98
+ export interface RecentChange {
99
+ at: number;
100
+ name: string;
101
+ outcome: 'added' | 'replaced' | 'applied' | 'reordered' | 'deleted' | 'enabled' | 'disabled' | 'rejected' | 'failed' | 'queued' | 'cancelled';
102
+ how: 'confirmed' | 'without asking';
103
+ detail?: string;
104
+ }
105
+ export type BrowserResponse = {
106
+ ok: true;
107
+ kind: 'status';
108
+ extensionVersion: string;
109
+ protonTabs: number;
110
+ } | {
111
+ ok: true;
112
+ kind: 'list_filters';
113
+ filters: ProtonFilter[];
114
+ queue?: QueuedAction[];
115
+ recent?: RecentChange[];
116
+ } | {
117
+ ok: true;
118
+ kind: 'propose_filter';
119
+ outcome: 'shown' | 'added' | 'replaced' | 'queued';
120
+ filterId?: string;
121
+ /** With a proposal to apply as well and no question: what became of applying it. */
122
+ apply?: 'done' | 'queued' | 'failed' | 'shown';
123
+ } | {
124
+ ok: true;
125
+ kind: 'apply_filter';
126
+ outcome: 'shown' | 'applied' | 'queued';
127
+ } | {
128
+ ok: true;
129
+ kind: 'reorder_filters';
130
+ outcome: 'shown' | 'reordered' | 'queued';
131
+ } | {
132
+ ok: true;
133
+ kind: 'delete_filter';
134
+ outcome: 'shown' | 'deleted' | 'queued';
135
+ } | {
136
+ ok: true;
137
+ kind: 'set_filter_status';
138
+ outcome: 'shown' | 'switched' | 'queued';
139
+ } | {
140
+ ok: false;
141
+ error: BrowserErrorCode;
142
+ message: string;
143
+ };
144
+ /** Generous bounds on shape. The real limits on names and scripts are in sieve.ts. */
145
+ export declare const LIMITS: {
146
+ readonly account: 320;
147
+ readonly name: 1000;
148
+ /** Above the longest script sieve.ts takes, so a stored filter just over it can still be read. */
149
+ readonly sieve: 60000;
150
+ readonly id: 256;
151
+ readonly message: 4000;
152
+ readonly version: 64;
153
+ readonly filters: 1000;
154
+ readonly moves: 50;
155
+ readonly queue: 100;
156
+ readonly recent: 50;
157
+ };
158
+ /** A request as one of the seven kinds, or nothing when it is anything else. */
159
+ export declare function parseRequest(value: unknown): BrowserRequest | undefined;
160
+ /** An answer as one of the known shapes, or nothing when it is anything else. */
161
+ export declare function parseResponse(value: unknown): BrowserResponse | undefined;
162
+ /** True for the ids the server and the connector put on a request: short and plain. */
163
+ export declare function isRequestId(value: unknown): value is string;