@bjorntech/key-ferry 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +209 -2
- package/SECURITY.md +87 -0
- package/dist/contracts.d.ts +133 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +29 -0
- package/dist/contracts.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/options.d.ts +44 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +260 -0
- package/dist/options.js.map +1 -0
- package/dist/plugin.d.ts +24 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +215 -0
- package/dist/plugin.js.map +1 -0
- package/dist/relay/index.d.ts +37 -0
- package/dist/relay/index.d.ts.map +1 -0
- package/dist/relay/index.js +480 -0
- package/dist/relay/index.js.map +1 -0
- package/dist/remote.d.ts +62 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +227 -0
- package/dist/remote.js.map +1 -0
- package/dist/rpc.d.ts +112 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +117 -0
- package/dist/rpc.js.map +1 -0
- package/dist/services/process.d.ts +56 -0
- package/dist/services/process.d.ts.map +1 -0
- package/dist/services/process.js +208 -0
- package/dist/services/process.js.map +1 -0
- package/dist/tui.d.ts +59 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/tui.js +93 -0
- package/dist/tui.js.map +1 -0
- package/dist/varlock/manager.d.ts +6 -0
- package/dist/varlock/manager.d.ts.map +1 -0
- package/dist/varlock/manager.js +425 -0
- package/dist/varlock/manager.js.map +1 -0
- package/dist/varlock/protocol.d.ts +67 -0
- package/dist/varlock/protocol.d.ts.map +1 -0
- package/dist/varlock/protocol.js +248 -0
- package/dist/varlock/protocol.js.map +1 -0
- package/docs/architecture.md +179 -0
- package/docs/quality.md +102 -0
- package/docs/releasing.md +149 -0
- package/docs/troubleshooting.md +214 -0
- package/examples/.env.schema +17 -0
- package/examples/opencode.jsonc +44 -0
- package/package.json +96 -4
package/dist/options.js
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { projectDirectory as brandProjectDirectory } from "./contracts.js";
|
|
3
|
+
const DEFAULT_STARTUP_TIMEOUT_MS = 30_000;
|
|
4
|
+
const DEFAULT_COMMAND_TIMEOUT_MS = 10_000;
|
|
5
|
+
const DEFAULT_RELOAD_TIMEOUT_MS = 30_000;
|
|
6
|
+
const DEFAULT_POLL_INTERVAL_MS = 100;
|
|
7
|
+
const MAX_TIMEOUT_MS = 10 * 60 * 1_000;
|
|
8
|
+
const MAX_RELOAD_TIMEOUT_MS = 15 * 60 * 1_000;
|
|
9
|
+
const HEADER_NAME = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
10
|
+
const HOP_BY_HOP_HEADERS = new Set([
|
|
11
|
+
"connection",
|
|
12
|
+
"keep-alive",
|
|
13
|
+
"proxy-authenticate",
|
|
14
|
+
"proxy-authorization",
|
|
15
|
+
"te",
|
|
16
|
+
"trailer",
|
|
17
|
+
"transfer-encoding",
|
|
18
|
+
"upgrade",
|
|
19
|
+
"host",
|
|
20
|
+
"content-length",
|
|
21
|
+
]);
|
|
22
|
+
const MCP_PROTOCOL_HEADERS = new Set([
|
|
23
|
+
"accept",
|
|
24
|
+
"content-type",
|
|
25
|
+
"mcp-session-id",
|
|
26
|
+
"mcp-protocol-version",
|
|
27
|
+
"last-event-id",
|
|
28
|
+
"origin",
|
|
29
|
+
]);
|
|
30
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31
|
+
const positiveInteger = (value, name, maximum) => {
|
|
32
|
+
if (typeof value !== "number" ||
|
|
33
|
+
!Number.isSafeInteger(value) ||
|
|
34
|
+
value < 1 ||
|
|
35
|
+
(maximum !== undefined && value > maximum))
|
|
36
|
+
throw new TypeError(`${name} must be a positive integer${maximum === undefined ? "" : ` no greater than ${maximum}`}`);
|
|
37
|
+
return value;
|
|
38
|
+
};
|
|
39
|
+
const stringArray = (value, name) => {
|
|
40
|
+
if (!Array.isArray(value) ||
|
|
41
|
+
value.length === 0 ||
|
|
42
|
+
value.some((item) => typeof item !== "string" || item.length === 0))
|
|
43
|
+
throw new TypeError(`${name} must be a non-empty array of non-empty strings`);
|
|
44
|
+
return [...value];
|
|
45
|
+
};
|
|
46
|
+
const unsafeName = (value) => value === "__proto__" || value === "prototype" || value === "constructor";
|
|
47
|
+
const environmentName = (value, name) => {
|
|
48
|
+
if (typeof value !== "string" ||
|
|
49
|
+
value.length === 0 ||
|
|
50
|
+
value.length > 256 ||
|
|
51
|
+
unsafeName(value) ||
|
|
52
|
+
!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
|
|
53
|
+
throw new TypeError(`${name} must be a valid environment name`);
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
};
|
|
57
|
+
function normalizeServer(name, value) {
|
|
58
|
+
if (!isRecord(value))
|
|
59
|
+
throw new TypeError(`servers.${name} must be an object`);
|
|
60
|
+
if ("remote" in value) {
|
|
61
|
+
if ("env" in value)
|
|
62
|
+
throw new TypeError(`servers.${name} cannot mix env and remote protection`);
|
|
63
|
+
return normalizeRemoteServer(name, value);
|
|
64
|
+
}
|
|
65
|
+
const env = value.env;
|
|
66
|
+
if (Array.isArray(env)) {
|
|
67
|
+
const keys = stringArray(env, `servers.${name}.env`).map((key) => environmentName(key, `servers.${name}.env`));
|
|
68
|
+
const result = Object.create(null);
|
|
69
|
+
for (const key of keys)
|
|
70
|
+
result[key] = key;
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
if (!isRecord(env))
|
|
74
|
+
throw new TypeError(`servers.${name}.env must be an array or object`);
|
|
75
|
+
const result = Object.create(null);
|
|
76
|
+
for (const [outputName, sourceName] of Object.entries(env)) {
|
|
77
|
+
const output = environmentName(outputName, `servers.${name}.env output`);
|
|
78
|
+
result[output] = environmentName(sourceName, `servers.${name}.env source`);
|
|
79
|
+
}
|
|
80
|
+
if (Object.keys(result).length === 0)
|
|
81
|
+
throw new TypeError(`servers.${name}.env must not be empty`);
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
function cleanHeaderPart(value, field) {
|
|
85
|
+
if (value === undefined)
|
|
86
|
+
return undefined;
|
|
87
|
+
if (typeof value !== "string" || value.length > 256 || /[\r\n\0]/.test(value)) {
|
|
88
|
+
throw new TypeError(`${field} must be a bounded string without control characters`);
|
|
89
|
+
}
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
function normalizeRemoteServer(name, value) {
|
|
93
|
+
const remote = value.remote;
|
|
94
|
+
if (!isRecord(remote) || !isRecord(remote.headers)) {
|
|
95
|
+
throw new TypeError(`servers.${name}.remote.headers must be a non-empty object`);
|
|
96
|
+
}
|
|
97
|
+
const result = Object.create(null);
|
|
98
|
+
const seen = new Set();
|
|
99
|
+
for (const [header, rawMapping] of Object.entries(remote.headers)) {
|
|
100
|
+
const lower = header.toLowerCase();
|
|
101
|
+
if (!HEADER_NAME.test(header) ||
|
|
102
|
+
unsafeName(header) ||
|
|
103
|
+
HOP_BY_HOP_HEADERS.has(lower) ||
|
|
104
|
+
MCP_PROTOCOL_HEADERS.has(lower) ||
|
|
105
|
+
lower === "set-cookie" ||
|
|
106
|
+
seen.has(lower)) {
|
|
107
|
+
throw new TypeError(`servers.${name}.remote.headers contains an invalid or duplicate header`);
|
|
108
|
+
}
|
|
109
|
+
seen.add(lower);
|
|
110
|
+
if (typeof rawMapping === "string") {
|
|
111
|
+
result[header] = environmentName(rawMapping, `servers.${name}.remote.headers.${header}`);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (!isRecord(rawMapping))
|
|
115
|
+
throw new TypeError(`servers.${name}.remote.headers.${header} must name an environment key`);
|
|
116
|
+
const env = environmentName(rawMapping.env, `servers.${name}.remote.headers.${header}.env`);
|
|
117
|
+
const prefix = cleanHeaderPart(rawMapping.prefix, `servers.${name}.remote.headers.${header}.prefix`);
|
|
118
|
+
const suffix = cleanHeaderPart(rawMapping.suffix, `servers.${name}.remote.headers.${header}.suffix`);
|
|
119
|
+
result[header] = {
|
|
120
|
+
env,
|
|
121
|
+
...(prefix === undefined ? {} : { prefix }),
|
|
122
|
+
...(suffix === undefined ? {} : { suffix }),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (Object.keys(result).length === 0)
|
|
126
|
+
throw new TypeError(`servers.${name}.remote.headers must not be empty`);
|
|
127
|
+
return { remote: { headers: result } };
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Decode untrusted OpenCode plugin options without touching process.env.
|
|
131
|
+
* `enabled: false` explicitly means no manager layer, MCP transform, or RPC
|
|
132
|
+
* is installed and existing MCP configuration is left untouched.
|
|
133
|
+
*/
|
|
134
|
+
export function parseOptions(raw, directory) {
|
|
135
|
+
const input = isRecord(raw) ? raw : {};
|
|
136
|
+
if ("failClosed" in input)
|
|
137
|
+
throw new TypeError("failClosed is not supported; protection is always fail-closed");
|
|
138
|
+
const enabled = input.enabled === undefined
|
|
139
|
+
? true
|
|
140
|
+
: typeof input.enabled === "boolean"
|
|
141
|
+
? input.enabled
|
|
142
|
+
: (() => {
|
|
143
|
+
throw new TypeError("enabled must be a boolean");
|
|
144
|
+
})();
|
|
145
|
+
const resolvedProjectDirectory = input.projectDirectory === undefined
|
|
146
|
+
? directory === undefined
|
|
147
|
+
? undefined
|
|
148
|
+
: brandProjectDirectory(directory)
|
|
149
|
+
: (() => {
|
|
150
|
+
if (typeof input.projectDirectory !== "string" ||
|
|
151
|
+
input.projectDirectory.trim().length === 0) {
|
|
152
|
+
throw new TypeError("projectDirectory must be a non-empty path");
|
|
153
|
+
}
|
|
154
|
+
return brandProjectDirectory(resolve(directory ?? process.cwd(), input.projectDirectory));
|
|
155
|
+
})();
|
|
156
|
+
const command = input.command === undefined ? ["varlock"] : stringArray(input.command, "command");
|
|
157
|
+
const startupTimeoutMs = input.startupTimeoutMs === undefined
|
|
158
|
+
? DEFAULT_STARTUP_TIMEOUT_MS
|
|
159
|
+
: positiveInteger(input.startupTimeoutMs, "startupTimeoutMs");
|
|
160
|
+
const commandTimeoutMs = input.commandTimeoutMs === undefined
|
|
161
|
+
? DEFAULT_COMMAND_TIMEOUT_MS
|
|
162
|
+
: positiveInteger(input.commandTimeoutMs, "commandTimeoutMs", MAX_TIMEOUT_MS);
|
|
163
|
+
// Accept the old spelling while emitting only the manager's canonical
|
|
164
|
+
// reloadTimeoutMs option. This avoids silently turning a refresh timeout
|
|
165
|
+
// into a startup timeout for existing configurations.
|
|
166
|
+
const usesLegacyReloadName = input.reloadTimeoutMs === undefined && input.refreshTimeoutMs !== undefined;
|
|
167
|
+
const reloadInput = input.reloadTimeoutMs ?? input.refreshTimeoutMs;
|
|
168
|
+
const reloadTimeoutMs = reloadInput === undefined
|
|
169
|
+
? DEFAULT_RELOAD_TIMEOUT_MS
|
|
170
|
+
: positiveInteger(reloadInput, "reloadTimeoutMs", usesLegacyReloadName ? 900_000 : MAX_RELOAD_TIMEOUT_MS);
|
|
171
|
+
const pollIntervalMs = input.pollIntervalMs === undefined
|
|
172
|
+
? DEFAULT_POLL_INTERVAL_MS
|
|
173
|
+
: positiveInteger(input.pollIntervalMs, "pollIntervalMs", 10_000);
|
|
174
|
+
const requireStrictEgress = input.requireStrictEgress === undefined
|
|
175
|
+
? true
|
|
176
|
+
: typeof input.requireStrictEgress === "boolean"
|
|
177
|
+
? input.requireStrictEgress
|
|
178
|
+
: (() => {
|
|
179
|
+
throw new TypeError("requireStrictEgress must be a boolean");
|
|
180
|
+
})();
|
|
181
|
+
const allowPrivateNetwork = input.allowPrivateNetwork === undefined
|
|
182
|
+
? false
|
|
183
|
+
: typeof input.allowPrivateNetwork === "boolean"
|
|
184
|
+
? input.allowPrivateNetwork
|
|
185
|
+
: (() => {
|
|
186
|
+
throw new TypeError("allowPrivateNetwork must be a boolean");
|
|
187
|
+
})();
|
|
188
|
+
const servers = Object.create(null);
|
|
189
|
+
if (input.servers !== undefined) {
|
|
190
|
+
if (!isRecord(input.servers))
|
|
191
|
+
throw new TypeError("servers must be an object");
|
|
192
|
+
for (const [name, value] of Object.entries(input.servers)) {
|
|
193
|
+
if (!name || unsafeName(name))
|
|
194
|
+
throw new TypeError("server names must be safe non-empty names");
|
|
195
|
+
servers[name] = normalizeServer(name, value);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const adapter = {
|
|
199
|
+
command,
|
|
200
|
+
startupTimeoutMs,
|
|
201
|
+
commandTimeoutMs,
|
|
202
|
+
reloadTimeoutMs,
|
|
203
|
+
pollIntervalMs,
|
|
204
|
+
requireStrictEgress,
|
|
205
|
+
allowPrivateNetwork,
|
|
206
|
+
servers,
|
|
207
|
+
};
|
|
208
|
+
// Existing consumers read this property directly. It is deliberately not
|
|
209
|
+
// enumerable so managerOptions can pass an exact canonical adapter shape.
|
|
210
|
+
Object.defineProperty(adapter, "refreshTimeoutMs", {
|
|
211
|
+
value: input.refreshTimeoutMs === undefined ? 900_000 : reloadTimeoutMs,
|
|
212
|
+
enumerable: false,
|
|
213
|
+
configurable: false,
|
|
214
|
+
});
|
|
215
|
+
const manager = {
|
|
216
|
+
enabled,
|
|
217
|
+
...(resolvedProjectDirectory === undefined
|
|
218
|
+
? {}
|
|
219
|
+
: { projectDirectory: resolvedProjectDirectory }),
|
|
220
|
+
adapter,
|
|
221
|
+
};
|
|
222
|
+
return {
|
|
223
|
+
enabled,
|
|
224
|
+
...(resolvedProjectDirectory === undefined
|
|
225
|
+
? {}
|
|
226
|
+
: { projectDirectory: resolvedProjectDirectory }),
|
|
227
|
+
adapter,
|
|
228
|
+
manager,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
export function managerOptions(options, directory) {
|
|
232
|
+
const environmentKeys = [
|
|
233
|
+
...new Set(Object.values(options.adapter.servers).flatMap((mapping) => {
|
|
234
|
+
if (isRemoteProtectionValue(mapping)) {
|
|
235
|
+
return Object.values(mapping.remote.headers).map((header) => typeof header === "string" ? header : header.env);
|
|
236
|
+
}
|
|
237
|
+
return Object.values(mapping);
|
|
238
|
+
})),
|
|
239
|
+
];
|
|
240
|
+
return {
|
|
241
|
+
projectDirectory: options.projectDirectory ?? brandProjectDirectory(directory),
|
|
242
|
+
owner: "key-ferry",
|
|
243
|
+
// Keep this object in lockstep with the manager adapter contract. In
|
|
244
|
+
// particular, server mappings are plugin concerns and must not leak into
|
|
245
|
+
// the Varlock process adapter.
|
|
246
|
+
adapter: {
|
|
247
|
+
command: [...options.adapter.command],
|
|
248
|
+
environmentKeys,
|
|
249
|
+
startupTimeoutMs: options.adapter.startupTimeoutMs,
|
|
250
|
+
commandTimeoutMs: options.adapter.commandTimeoutMs,
|
|
251
|
+
reloadTimeoutMs: options.adapter.reloadTimeoutMs,
|
|
252
|
+
pollIntervalMs: options.adapter.pollIntervalMs,
|
|
253
|
+
requireStrictEgress: options.adapter.requireStrictEgress,
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function isRemoteProtectionValue(value) {
|
|
258
|
+
return isRecord(value) && isRecord(value.remote) && isRecord(value.remote.headers);
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Mcp, Plugin } from "@opencode/plugin/effect";
|
|
2
|
+
import { Types } from "effect";
|
|
3
|
+
import type { ProjectKeyFerryManagerFactory, ResolvedEnvironment } from "./contracts.js";
|
|
4
|
+
import { type ValidatedOptions } from "./options.js";
|
|
5
|
+
import { type RemoteRelayFactory, type RemoteRelayHandle } from "./remote.js";
|
|
6
|
+
export interface McpEditor {
|
|
7
|
+
list(): readonly [string, Types.DeepMutable<Mcp.ServerConfig>][];
|
|
8
|
+
get(name: string): Types.DeepMutable<Mcp.ServerConfig> | undefined;
|
|
9
|
+
update(name: string, update: (config: Types.DeepMutable<Mcp.ServerConfig>) => void): void;
|
|
10
|
+
}
|
|
11
|
+
export interface ProtectionState {
|
|
12
|
+
readonly ready: boolean;
|
|
13
|
+
readonly environment: ResolvedEnvironment;
|
|
14
|
+
readonly remoteHandles?: ReadonlyMap<string, RemoteRelayHandle>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Apply only explicitly configured local protections. A selected remote
|
|
18
|
+
* server, missing key, or unavailable manager is disabled rather than falling
|
|
19
|
+
* back to direct transport.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyProtection(editor: McpEditor, options: ValidatedOptions["adapter"], state: ProtectionState): void;
|
|
22
|
+
/** Construct the native OpenCode V2 plugin. The real manager is injected later. */
|
|
23
|
+
export declare function makePlugin(factory: ProjectKeyFerryManagerFactory, relayFactory?: RemoteRelayFactory): Plugin.Plugin;
|
|
24
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAiB,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EACV,6BAA6B,EAE7B,mBAAmB,EAEpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAML,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EAEvB,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,SAAS;IACxB,IAAI,IAAI,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;IACjE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACnE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;CAC3F;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CACjE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,EACpC,KAAK,EAAE,eAAe,GACrB,IAAI,CAoDN;AAwCD,mFAAmF;AACnF,wBAAgB,UAAU,CACxB,OAAO,EAAE,6BAA6B,EACtC,YAAY,CAAC,EAAE,kBAAkB,GAChC,MAAM,CAAC,MAAM,CAqKf"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { Mcp, Plugin } from "@opencode/plugin/effect";
|
|
2
|
+
import { Effect, Scope, Types } from "effect";
|
|
3
|
+
import { ProjectKeyFerryManager } from "./contracts.js";
|
|
4
|
+
import { managerOptions, parseOptions, } from "./options.js";
|
|
5
|
+
import { makeRemoteRelayCoordinator, RELAY_AUTH_HEADER, safeForwardHeaders, isRemoteProtection, } from "./remote.js";
|
|
6
|
+
import { KeyFerryRpc, publicMessage, rpcError, sanitizeStatus } from "./rpc.js";
|
|
7
|
+
/**
|
|
8
|
+
* Apply only explicitly configured local protections. A selected remote
|
|
9
|
+
* server, missing key, or unavailable manager is disabled rather than falling
|
|
10
|
+
* back to direct transport.
|
|
11
|
+
*/
|
|
12
|
+
export function applyProtection(editor, options, state) {
|
|
13
|
+
for (const [name, mapping] of Object.entries(options.servers)) {
|
|
14
|
+
const server = editor.get(name);
|
|
15
|
+
if (!server)
|
|
16
|
+
continue;
|
|
17
|
+
if (isRemoteProtection(mapping)) {
|
|
18
|
+
const handle = state.remoteHandles?.get(name);
|
|
19
|
+
editor.update(name, (config) => {
|
|
20
|
+
if (config.type !== "remote" || config.oauth !== false || !state.ready || !handle) {
|
|
21
|
+
config.disabled = true;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const headers = safeForwardHeaders(config.headers, mapping);
|
|
25
|
+
if (headers === undefined) {
|
|
26
|
+
config.disabled = true;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
config.url = handle.localUrl;
|
|
30
|
+
config.headers = { ...headers, [RELAY_AUTH_HEADER]: handle.downstreamToken };
|
|
31
|
+
// Preserve an intentional user disablement. The transformed config is
|
|
32
|
+
// never allowed to enable a server disabled in project configuration.
|
|
33
|
+
if (server.disabled !== true)
|
|
34
|
+
config.disabled = false;
|
|
35
|
+
});
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (server.type !== "local") {
|
|
39
|
+
editor.update(name, (config) => {
|
|
40
|
+
config.disabled = true;
|
|
41
|
+
});
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const resolved = Object.create(null);
|
|
45
|
+
let complete = state.ready;
|
|
46
|
+
for (const [outputName, sourceName] of Object.entries(mapping)) {
|
|
47
|
+
const value = state.environment[sourceName];
|
|
48
|
+
if (value === undefined)
|
|
49
|
+
complete = false;
|
|
50
|
+
else
|
|
51
|
+
resolved[outputName] = value;
|
|
52
|
+
}
|
|
53
|
+
editor.update(name, (config) => {
|
|
54
|
+
if (config.type !== "local") {
|
|
55
|
+
config.disabled = true;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (!complete) {
|
|
59
|
+
config.disabled = true;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
config.environment = { ...(config.environment ?? {}), ...resolved };
|
|
63
|
+
// Preserve an intentional user disablement. Protection never enables a
|
|
64
|
+
// server that was explicitly disabled in project configuration.
|
|
65
|
+
if (server.disabled !== true)
|
|
66
|
+
config.disabled = false;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const ensureState = (manager) => manager
|
|
71
|
+
.withExclusive(Effect.gen(function* () {
|
|
72
|
+
const status = yield* manager.ensureStarted;
|
|
73
|
+
const environment = yield* manager.environment;
|
|
74
|
+
return { status: sanitizeStatus(status), environment };
|
|
75
|
+
}))
|
|
76
|
+
.pipe(Effect.catch((error) => manager.status.pipe(Effect.map((status) => ({
|
|
77
|
+
status: sanitizeStatus({ ...status, error }),
|
|
78
|
+
environment: {},
|
|
79
|
+
})))));
|
|
80
|
+
function snapshotServers(editor) {
|
|
81
|
+
const result = new Map();
|
|
82
|
+
for (const [name, config] of editor.list()) {
|
|
83
|
+
if (config.type !== "remote")
|
|
84
|
+
continue;
|
|
85
|
+
result.set(name, {
|
|
86
|
+
type: "remote",
|
|
87
|
+
url: config.url,
|
|
88
|
+
...(config.headers === undefined ? {} : { headers: { ...config.headers } }),
|
|
89
|
+
...(config.oauth === undefined ? {} : { oauth: config.oauth }),
|
|
90
|
+
...(config.disabled === undefined ? {} : { disabled: config.disabled }),
|
|
91
|
+
...(config.codemode === undefined ? {} : { codemode: config.codemode }),
|
|
92
|
+
...(config.timeout === undefined ? {} : { timeout: config.timeout }),
|
|
93
|
+
...(config.protocol === undefined ? {} : { protocol: config.protocol }),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
/** Construct the native OpenCode V2 plugin. The real manager is injected later. */
|
|
99
|
+
export function makePlugin(factory, relayFactory) {
|
|
100
|
+
return Plugin.define({
|
|
101
|
+
id: "key-ferry",
|
|
102
|
+
effect: (ctx) => {
|
|
103
|
+
const parsed = parseOptions(ctx.options, ctx.location.project.directory);
|
|
104
|
+
if (!parsed.enabled)
|
|
105
|
+
return Effect.void;
|
|
106
|
+
const program = Effect.gen(function* () {
|
|
107
|
+
const pluginScope = yield* Effect.scope;
|
|
108
|
+
const manager = yield* ProjectKeyFerryManager;
|
|
109
|
+
let state = { ready: false, environment: {} };
|
|
110
|
+
let observedGeneration = -1;
|
|
111
|
+
let remoteDiagnostics = [];
|
|
112
|
+
let serverSnapshots = new Map();
|
|
113
|
+
const remote = makeRemoteRelayCoordinator(relayFactory, parsed.adapter.allowPrivateNetwork);
|
|
114
|
+
const setState = (next) => {
|
|
115
|
+
state = next;
|
|
116
|
+
};
|
|
117
|
+
const publicStatus = (status) => sanitizeStatus({
|
|
118
|
+
...status,
|
|
119
|
+
...(remoteDiagnostics.length === 0 ? {} : { diagnostics: remoteDiagnostics }),
|
|
120
|
+
});
|
|
121
|
+
const reconcileRemote = (status, environment) => Effect.gen(function* () {
|
|
122
|
+
// A health failure may have stopped and removed the current handles.
|
|
123
|
+
// Reconcile from the manager capability again during doctor, rather
|
|
124
|
+
// than treating doctor as a metadata-only operation.
|
|
125
|
+
if (status.phase === "ready") {
|
|
126
|
+
if (!(yield* remote.health))
|
|
127
|
+
yield* remote.stopAll;
|
|
128
|
+
yield* Effect.provideService(remote.reconcile(serverSnapshots, parsed.adapter.servers, environment, status.generation), Scope.Scope, pluginScope);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
yield* remote.stopAll;
|
|
132
|
+
}
|
|
133
|
+
remoteDiagnostics = remote.diagnostics;
|
|
134
|
+
const next = {
|
|
135
|
+
ready: status.phase === "ready",
|
|
136
|
+
environment,
|
|
137
|
+
remoteHandles: remote.handles,
|
|
138
|
+
};
|
|
139
|
+
setState(next);
|
|
140
|
+
return next;
|
|
141
|
+
});
|
|
142
|
+
yield* ctx.mcp.transform((editor) => {
|
|
143
|
+
serverSnapshots = snapshotServers(editor);
|
|
144
|
+
applyProtection(editor, parsed.adapter, { ...state, remoteHandles: remote.handles });
|
|
145
|
+
});
|
|
146
|
+
const initial = yield* ensureState(manager);
|
|
147
|
+
yield* reconcileRemote(initial.status, initial.environment);
|
|
148
|
+
observedGeneration = initial.status.generation;
|
|
149
|
+
yield* ctx.mcp.reload();
|
|
150
|
+
yield* ctx.rpc.register(KeyFerryRpc, {
|
|
151
|
+
status: () => manager.status.pipe(Effect.map(publicStatus)),
|
|
152
|
+
refresh: (_, context) => manager.withExclusive(Effect.gen(function* () {
|
|
153
|
+
yield* remote.stopAll;
|
|
154
|
+
setState({ ready: false, environment: {}, remoteHandles: remote.handles });
|
|
155
|
+
yield* ctx.mcp.reload();
|
|
156
|
+
const status = yield* manager.refresh;
|
|
157
|
+
const environment = yield* manager.environment;
|
|
158
|
+
yield* reconcileRemote(status, environment);
|
|
159
|
+
yield* ctx.mcp.reload();
|
|
160
|
+
return publicStatus(status);
|
|
161
|
+
}).pipe(Effect.catch((error) => Effect.sync(() => {
|
|
162
|
+
remoteDiagnostics = remote.diagnostics;
|
|
163
|
+
setState({ ready: false, environment: {}, remoteHandles: remote.handles });
|
|
164
|
+
}).pipe(Effect.andThen(ctx.mcp.reload()), Effect.andThen(Effect.fail(context.error("unavailable", publicMessage(error), rpcError(error)))))))),
|
|
165
|
+
doctor: (_, context) => manager.withExclusive(Effect.gen(function* () {
|
|
166
|
+
const next = yield* ensureState(manager);
|
|
167
|
+
yield* reconcileRemote(next.status, next.environment);
|
|
168
|
+
yield* ctx.mcp.reload();
|
|
169
|
+
return publicStatus(next.status);
|
|
170
|
+
}).pipe(Effect.catch((error) => Effect.fail(context.error("unavailable", publicMessage(error), rpcError(error)))))),
|
|
171
|
+
});
|
|
172
|
+
// The manager owns process health. Poll only safe metadata and disable
|
|
173
|
+
// protected servers immediately if the owned process dies. A changed
|
|
174
|
+
// generation gets a fresh, allowlisted environment before reconnecting.
|
|
175
|
+
yield* Effect.forkScoped(Effect.forever(Effect.gen(function* () {
|
|
176
|
+
yield* Effect.sleep("30 seconds");
|
|
177
|
+
const status = yield* manager.status;
|
|
178
|
+
if (status.phase !== "ready") {
|
|
179
|
+
if (state.ready || remote.handles.size > 0) {
|
|
180
|
+
yield* remote.stopAll;
|
|
181
|
+
setState({ ready: false, environment: {}, remoteHandles: remote.handles });
|
|
182
|
+
yield* ctx.mcp.reload();
|
|
183
|
+
}
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const relayHealthy = yield* remote.health;
|
|
187
|
+
if (!relayHealthy) {
|
|
188
|
+
yield* remote.stopAll;
|
|
189
|
+
setState({ ready: false, environment: {}, remoteHandles: remote.handles });
|
|
190
|
+
yield* ctx.mcp.reload();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (status.generation === observedGeneration && state.ready)
|
|
194
|
+
return;
|
|
195
|
+
yield* remote.stopAll;
|
|
196
|
+
const next = yield* ensureState(manager);
|
|
197
|
+
observedGeneration = next.status.generation;
|
|
198
|
+
if (next.status.phase === "ready") {
|
|
199
|
+
yield* Effect.provideService(remote.reconcile(serverSnapshots, parsed.adapter.servers, next.environment, next.status.generation), Scope.Scope, pluginScope);
|
|
200
|
+
remoteDiagnostics = remote.diagnostics;
|
|
201
|
+
}
|
|
202
|
+
setState({
|
|
203
|
+
ready: next.status.phase === "ready",
|
|
204
|
+
environment: next.environment,
|
|
205
|
+
remoteHandles: remote.handles,
|
|
206
|
+
});
|
|
207
|
+
yield* ctx.mcp.reload();
|
|
208
|
+
})).pipe(Effect.catch(() => Effect.void)));
|
|
209
|
+
yield* Effect.addFinalizer(() => remote.stopAll);
|
|
210
|
+
});
|
|
211
|
+
return Effect.provide(program, factory.layer(managerOptions(parsed, ctx.location.project.directory))).pipe(Effect.catch(() => Effect.void));
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
export declare const RELAY_AUTH_HEADER = "x-varlock-relay-token";
|
|
3
|
+
export type RelayErrorCode = "invalid-config" | "bind-failed" | "unauthorized" | "path-denied" | "body-too-large" | "upstream-connect-failed" | "upstream-tls-failed" | "timeout" | "closed" | "unsupported" | "io";
|
|
4
|
+
declare const RelayError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
5
|
+
readonly _tag: "RelayError";
|
|
6
|
+
} & Readonly<A>;
|
|
7
|
+
export declare class RelayError extends RelayError_base<{
|
|
8
|
+
readonly code: RelayErrorCode;
|
|
9
|
+
readonly message: string;
|
|
10
|
+
}> {
|
|
11
|
+
}
|
|
12
|
+
export interface RelayConfig {
|
|
13
|
+
readonly upstreamUrl: string;
|
|
14
|
+
readonly proxyUrl: string;
|
|
15
|
+
readonly managerCaPem: string;
|
|
16
|
+
readonly placeholderHeaders: Readonly<Record<string, string>>;
|
|
17
|
+
readonly oauth: false;
|
|
18
|
+
readonly maxRequestBytes?: number;
|
|
19
|
+
readonly connectTimeoutMs?: number;
|
|
20
|
+
readonly idleTimeoutMs?: number;
|
|
21
|
+
readonly maxConnections?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface RelayHealth {
|
|
24
|
+
readonly listening: boolean;
|
|
25
|
+
readonly activeRequests: number;
|
|
26
|
+
readonly localUrl: string;
|
|
27
|
+
}
|
|
28
|
+
export interface RelayHandle {
|
|
29
|
+
readonly localUrl: string;
|
|
30
|
+
/** Internal capability. Never include this in public RPC, logs, or status. */
|
|
31
|
+
readonly downstreamToken: string;
|
|
32
|
+
readonly health: Effect.Effect<RelayHealth>;
|
|
33
|
+
readonly stop: Effect.Effect<void, RelayError>;
|
|
34
|
+
}
|
|
35
|
+
export declare const startRelay: (config: RelayConfig) => Effect.Effect<RelayHandle, RelayError, import("effect/Scope").Scope>;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/relay/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEtC,eAAO,MAAM,iBAAiB,0BAA0B,CAAC;AAEzD,MAAM,MAAM,cAAc,GACtB,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,aAAa,GACb,gBAAgB,GAChB,yBAAyB,GACzB,qBAAqB,GACrB,SAAS,GACT,QAAQ,GACR,aAAa,GACb,IAAI,CAAC;;;;AAET,qBAAa,UAAW,SAAQ,gBAA+B;IAC7D,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;CAChD;AA8gBD,eAAO,MAAM,UAAU,WAtOb,WAAW,KAClB,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,cAAc,EAAE,KAAK,CAqOvC,CAAC"}
|