@bjorntech/key-ferry 0.0.0-stage → 0.1.4

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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +209 -2
  3. package/SECURITY.md +87 -0
  4. package/dist/contracts.d.ts +133 -0
  5. package/dist/contracts.d.ts.map +1 -0
  6. package/dist/contracts.js +29 -0
  7. package/dist/contracts.js.map +1 -0
  8. package/dist/index.d.ts +7 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +12 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/options.d.ts +44 -0
  13. package/dist/options.d.ts.map +1 -0
  14. package/dist/options.js +260 -0
  15. package/dist/options.js.map +1 -0
  16. package/dist/plugin.d.ts +24 -0
  17. package/dist/plugin.d.ts.map +1 -0
  18. package/dist/plugin.js +215 -0
  19. package/dist/plugin.js.map +1 -0
  20. package/dist/relay/index.d.ts +37 -0
  21. package/dist/relay/index.d.ts.map +1 -0
  22. package/dist/relay/index.js +480 -0
  23. package/dist/relay/index.js.map +1 -0
  24. package/dist/remote.d.ts +62 -0
  25. package/dist/remote.d.ts.map +1 -0
  26. package/dist/remote.js +227 -0
  27. package/dist/remote.js.map +1 -0
  28. package/dist/rpc.d.ts +112 -0
  29. package/dist/rpc.d.ts.map +1 -0
  30. package/dist/rpc.js +117 -0
  31. package/dist/rpc.js.map +1 -0
  32. package/dist/services/process.d.ts +56 -0
  33. package/dist/services/process.d.ts.map +1 -0
  34. package/dist/services/process.js +208 -0
  35. package/dist/services/process.js.map +1 -0
  36. package/dist/tui.d.ts +59 -0
  37. package/dist/tui.d.ts.map +1 -0
  38. package/dist/tui.js +93 -0
  39. package/dist/tui.js.map +1 -0
  40. package/dist/varlock/manager.d.ts +6 -0
  41. package/dist/varlock/manager.d.ts.map +1 -0
  42. package/dist/varlock/manager.js +425 -0
  43. package/dist/varlock/manager.js.map +1 -0
  44. package/dist/varlock/protocol.d.ts +67 -0
  45. package/dist/varlock/protocol.d.ts.map +1 -0
  46. package/dist/varlock/protocol.js +248 -0
  47. package/dist/varlock/protocol.js.map +1 -0
  48. package/docs/architecture.md +179 -0
  49. package/docs/quality.md +102 -0
  50. package/docs/releasing.md +149 -0
  51. package/docs/troubleshooting.md +214 -0
  52. package/examples/.env.schema +17 -0
  53. package/examples/opencode.jsonc +44 -0
  54. package/package.json +96 -4
@@ -0,0 +1,208 @@
1
+ import { spawn } from "node:child_process";
2
+ import { Context, Data, Duration, Effect, Layer } from "effect";
3
+ /** Deliberately contains no command, arguments, or captured output. */
4
+ export class ProcessError extends Data.TaggedError("ProcessError") {
5
+ }
6
+ export class Process extends Context.Service()("key-ferry/Process") {
7
+ }
8
+ const defaultMaxBytes = 1024 * 1024;
9
+ const defaultGraceMs = 500;
10
+ const safeMessage = (phase, code) => `${phase} failed (${code})`;
11
+ const error = (phase, code, extra = {}) => new ProcessError({ phase, code, message: safeMessage(phase, code), ...extra });
12
+ const kill = (child, graceMs) => Effect.callback((resume) => {
13
+ let settled = false;
14
+ let timer;
15
+ const finish = () => {
16
+ if (!settled) {
17
+ settled = true;
18
+ if (timer)
19
+ clearTimeout(timer);
20
+ child.removeListener("close", finish);
21
+ resume(Effect.void);
22
+ }
23
+ };
24
+ child.once("close", finish);
25
+ if (child.exitCode !== null || child.signalCode !== null)
26
+ return finish();
27
+ try {
28
+ child.kill("SIGTERM");
29
+ }
30
+ catch {
31
+ return finish();
32
+ }
33
+ timer = setTimeout(() => {
34
+ if (child.exitCode === null && child.signalCode === null) {
35
+ try {
36
+ child.kill("SIGKILL");
37
+ }
38
+ catch {
39
+ // The process may have exited between the check and kill.
40
+ }
41
+ }
42
+ finish();
43
+ }, Math.max(0, graceMs));
44
+ return Effect.sync(() => {
45
+ if (timer)
46
+ clearTimeout(timer);
47
+ child.removeListener("close", finish);
48
+ });
49
+ });
50
+ const spawnRaw = (input) => Effect.acquireRelease(Effect.callback((resume) => {
51
+ let child;
52
+ try {
53
+ // shell is intentionally absent. Never inherit or mutate global env.
54
+ child = spawn(input.executable, [...input.args], {
55
+ cwd: input.cwd,
56
+ // An omitted environment is intentionally isolated. Callers that
57
+ // need the trusted Varlock resolver environment must pass it
58
+ // deliberately; never inherit the host process environment.
59
+ env: input.env ? { ...input.env } : {},
60
+ shell: false,
61
+ detached: false,
62
+ stdio: ["ignore", "ignore", "ignore"],
63
+ });
64
+ }
65
+ catch {
66
+ resume(Effect.fail(error("spawn", "spawn-failed")));
67
+ return;
68
+ }
69
+ const completion = Effect.callback((done) => {
70
+ const close = (code, signal) => {
71
+ child.removeListener("error", onError);
72
+ if (code === 0)
73
+ done(Effect.succeed({ code, signal }));
74
+ else
75
+ done(Effect.fail(error("exit", code === null ? "signal" : "non-zero", {
76
+ exitCode: code ?? undefined,
77
+ signal: signal ?? undefined,
78
+ })));
79
+ };
80
+ const onError = () => done(Effect.fail(error("running", "io")));
81
+ child.once("close", close);
82
+ child.once("error", onError);
83
+ return Effect.sync(() => {
84
+ child.removeListener("close", close);
85
+ child.removeListener("error", onError);
86
+ });
87
+ });
88
+ let stopped = false;
89
+ const stop = Effect.suspend(() => {
90
+ if (stopped)
91
+ return Effect.void;
92
+ stopped = true;
93
+ // A stop is bounded by kill's grace period, but must not be
94
+ // interruptible between SIGTERM and the SIGKILL fallback. Otherwise
95
+ // an interrupted stop can clear the fallback timer while `stopped`
96
+ // prevents scope finalization from trying again.
97
+ return Effect.uninterruptible(kill(child, input.terminateGraceMs ?? defaultGraceMs));
98
+ });
99
+ resume(Effect.succeed({
100
+ pid: child.pid,
101
+ completion,
102
+ health: Effect.sync(() => ({
103
+ pid: child.pid,
104
+ running: child.exitCode === null && child.signalCode === null,
105
+ exit: child.exitCode !== null || child.signalCode !== null
106
+ ? { code: child.exitCode, signal: child.signalCode }
107
+ : undefined,
108
+ })),
109
+ stop,
110
+ }));
111
+ }), (process) => process.stop.pipe(Effect.catch(() => Effect.void)));
112
+ const run = (input) => {
113
+ const maxBytes = input.maxBytes ?? defaultMaxBytes;
114
+ const spawned = Effect.callback((resume, signal) => {
115
+ let child;
116
+ try {
117
+ child = spawn(input.executable, [...input.args], {
118
+ cwd: input.cwd,
119
+ env: input.env ? { ...input.env } : {},
120
+ shell: false,
121
+ detached: false,
122
+ stdio: ["ignore", "pipe", "pipe"],
123
+ });
124
+ }
125
+ catch {
126
+ resume(Effect.fail(error("spawn", "spawn-failed")));
127
+ return;
128
+ }
129
+ let stdout = "";
130
+ let stderr = "";
131
+ let limited = false;
132
+ const onData = (which) => (chunk) => {
133
+ if (which === "stdout")
134
+ stdout += chunk.toString("utf8");
135
+ else
136
+ stderr += chunk.toString("utf8");
137
+ if ((which === "stdout" ? Buffer.byteLength(stdout) : Buffer.byteLength(stderr)) > maxBytes &&
138
+ !limited) {
139
+ limited = true;
140
+ try {
141
+ child.kill("SIGTERM");
142
+ }
143
+ catch {
144
+ /* already exited */
145
+ }
146
+ setTimeout(() => {
147
+ if (child.exitCode === null && child.signalCode === null) {
148
+ try {
149
+ child.kill("SIGKILL");
150
+ }
151
+ catch {
152
+ /* already exited */
153
+ }
154
+ }
155
+ }, defaultGraceMs);
156
+ }
157
+ };
158
+ const out = onData("stdout");
159
+ const err = onData("stderr");
160
+ child.stdout?.on("data", out);
161
+ child.stderr?.on("data", err);
162
+ const close = (code, sig) => {
163
+ if (limited)
164
+ resume(Effect.fail(error("capture-limit", "capture-limit")));
165
+ else if (code === 0)
166
+ resume(Effect.succeed({ code, signal: sig, stdout, stderr }));
167
+ else
168
+ resume(Effect.fail(error("exit", code === null ? "signal" : "non-zero", {
169
+ exitCode: code ?? undefined,
170
+ signal: sig ?? undefined,
171
+ })));
172
+ };
173
+ child.once("close", close);
174
+ child.once("error", () => resume(Effect.fail(error("running", "io"))));
175
+ signal.addEventListener("abort", () => {
176
+ try {
177
+ child.kill("SIGTERM");
178
+ }
179
+ catch {
180
+ /* already exited */
181
+ }
182
+ setTimeout(() => {
183
+ if (child.exitCode === null && child.signalCode === null) {
184
+ try {
185
+ child.kill("SIGKILL");
186
+ }
187
+ catch {
188
+ /* already exited */
189
+ }
190
+ }
191
+ }, defaultGraceMs);
192
+ }, { once: true });
193
+ return Effect.sync(() => {
194
+ child.stdout?.removeListener("data", out);
195
+ child.stderr?.removeListener("data", err);
196
+ child.removeListener("close", close);
197
+ });
198
+ });
199
+ const bounded = input.timeoutMs === undefined
200
+ ? spawned
201
+ : spawned.pipe(Effect.timeoutOrElse({
202
+ duration: Duration.millis(input.timeoutMs),
203
+ orElse: () => Effect.fail(error("timeout", "timeout")),
204
+ }));
205
+ return bounded;
206
+ };
207
+ export const ProcessLive = Layer.succeed(Process, Process.of({ run, spawn: spawnRaw }));
208
+ //# sourceMappingURL=process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/services/process.ts"],"names":[],"mappings":"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"}
package/dist/tui.d.ts ADDED
@@ -0,0 +1,59 @@
1
+ import { Plugin } from "@opencode/plugin/tui";
2
+ export interface SafeStatusView {
3
+ readonly phase: string;
4
+ readonly generation: number;
5
+ readonly diagnostics?: readonly {
6
+ readonly server: string;
7
+ readonly code: string;
8
+ readonly message: string;
9
+ }[];
10
+ readonly error?: {
11
+ readonly code: string;
12
+ readonly message: string;
13
+ readonly retryable: boolean;
14
+ };
15
+ }
16
+ export interface TuiActions {
17
+ readonly status: () => Promise<SafeStatusView>;
18
+ readonly refresh: () => Promise<SafeStatusView>;
19
+ readonly doctor: () => Promise<SafeStatusView>;
20
+ readonly show: (title: string, message: string, variant: "info" | "success" | "warning" | "error") => void;
21
+ }
22
+ export declare function formatStatus(status: SafeStatusView): string;
23
+ export declare function createCommands(actions: TuiActions): readonly [{
24
+ readonly id: "key-ferry.status";
25
+ readonly title: "Key Ferry: Status";
26
+ readonly description: "Show safe Key Ferry sidecar state";
27
+ readonly group: "Varlock";
28
+ readonly palette: true;
29
+ readonly slash: {
30
+ readonly name: "key-ferry-status";
31
+ readonly aliases: string[];
32
+ };
33
+ readonly run: () => Promise<void>;
34
+ }, {
35
+ readonly id: "key-ferry.refresh";
36
+ readonly title: "Key Ferry: Refresh";
37
+ readonly description: "Refresh the protected project environment";
38
+ readonly group: "Varlock";
39
+ readonly palette: true;
40
+ readonly slash: {
41
+ readonly name: "key-ferry-refresh";
42
+ readonly aliases: string[];
43
+ };
44
+ readonly run: () => Promise<void>;
45
+ }, {
46
+ readonly id: "key-ferry.doctor";
47
+ readonly title: "Key Ferry: Doctor";
48
+ readonly description: "Check Varlock readiness and protected connections";
49
+ readonly group: "Varlock";
50
+ readonly palette: true;
51
+ readonly slash: {
52
+ readonly name: "key-ferry-doctor";
53
+ readonly aliases: string[];
54
+ };
55
+ readonly run: () => Promise<void>;
56
+ }];
57
+ declare const _default: Plugin.Definition;
58
+ export default _default;
59
+ //# sourceMappingURL=tui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS;QAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;CACnG;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,QAAQ,CAAC,IAAI,EAAE,CACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,KAC9C,IAAI,CAAC;CACX;AAuBD,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAO3D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,UAAU;;;;;;;;0BAuBe,MAAM,EAAE;;;;;;;;;;;0BASN,MAAM,EAAE;;;;;;;;;;;0BASV,MAAM,EAAE;;;GAIxE;;AAED,wBAwBG"}
package/dist/tui.js ADDED
@@ -0,0 +1,93 @@
1
+ import { Plugin } from "@opencode/plugin/tui";
2
+ import { KeyFerryRpc } from "./rpc.js";
3
+ const errorMessage = (error) => {
4
+ if (typeof error !== "object" || error === null)
5
+ return "Varlock is unavailable";
6
+ const code = "code" in error && typeof error.code === "string" ? error.code : "unavailable";
7
+ switch (code) {
8
+ case "invalid_config":
9
+ return "Varlock configuration is invalid";
10
+ case "start_failed":
11
+ return "Varlock could not start";
12
+ case "refresh_failed":
13
+ return "Varlock refresh failed";
14
+ case "timeout":
15
+ return "Varlock operation timed out";
16
+ case "not_ready":
17
+ return "Varlock is not ready";
18
+ case "protocol_error":
19
+ return "Varlock returned an invalid response";
20
+ default:
21
+ return "Varlock is unavailable";
22
+ }
23
+ };
24
+ export function formatStatus(status) {
25
+ const lines = status.error
26
+ ? [`${status.error.message} (${status.error.code})`]
27
+ : [`State: ${status.phase}`, `Generation: ${status.generation}`];
28
+ for (const item of status.diagnostics ?? [])
29
+ lines.push(`${item.server}: ${item.message} (${item.code})`);
30
+ return lines.join("\n");
31
+ }
32
+ export function createCommands(actions) {
33
+ const run = (title, operation, success) => async () => {
34
+ actions.show(title, "Working…", "info");
35
+ try {
36
+ const status = await operation();
37
+ actions.show(title, `${success}\n\n${formatStatus(status)}`, status.error ? "warning" : "success");
38
+ }
39
+ catch (error) {
40
+ actions.show(title, errorMessage(error), "error");
41
+ }
42
+ };
43
+ return [
44
+ {
45
+ id: "key-ferry.status",
46
+ title: "Key Ferry: Status",
47
+ description: "Show safe Key Ferry sidecar state",
48
+ group: "Varlock",
49
+ palette: true,
50
+ slash: { name: "key-ferry-status", aliases: ["vstatus"] },
51
+ run: run("Varlock status", actions.status, "Status loaded"),
52
+ },
53
+ {
54
+ id: "key-ferry.refresh",
55
+ title: "Key Ferry: Refresh",
56
+ description: "Refresh the protected project environment",
57
+ group: "Varlock",
58
+ palette: true,
59
+ slash: { name: "key-ferry-refresh", aliases: ["vrefresh"] },
60
+ run: run("Varlock refresh", actions.refresh, "Refresh completed"),
61
+ },
62
+ {
63
+ id: "key-ferry.doctor",
64
+ title: "Key Ferry: Doctor",
65
+ description: "Check Varlock readiness and protected connections",
66
+ group: "Varlock",
67
+ palette: true,
68
+ slash: { name: "key-ferry-doctor", aliases: ["vdoctor"] },
69
+ run: run("Varlock doctor", actions.doctor, "Check completed"),
70
+ },
71
+ ];
72
+ }
73
+ export default Plugin.define({
74
+ id: "key-ferry.tui",
75
+ setup(context) {
76
+ // The server RPC uses Effect Schema. The generated Promise client exposes
77
+ // the same validated wire contract, but its declaration only admits
78
+ // PortableDefinition, so this boundary is typed at the safe response.
79
+ const rpc = context.client.rpc(KeyFerryRpc);
80
+ const show = (title, message, variant) => context.ui.toast.show({ title, message, variant });
81
+ context.keymap.layer(() => ({
82
+ mode: "global",
83
+ priority: 20,
84
+ commands: createCommands({
85
+ status: () => rpc.status({}),
86
+ refresh: () => rpc.refresh({}),
87
+ doctor: () => rpc.doctor({}),
88
+ show,
89
+ }),
90
+ }));
91
+ },
92
+ });
93
+ //# sourceMappingURL=tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui.js","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Layer } from "effect";
2
+ import { ProjectKeyFerryManager, type ProjectKeyFerryManagerFactory, type ProjectKeyFerryManagerOptions, VarlockError } from "../contracts.js";
3
+ import { Process } from "../services/process.js";
4
+ export declare function makeProjectKeyFerryManager(options: ProjectKeyFerryManagerOptions, processLayer?: Layer.Layer<Process, never, never>): Layer.Layer<ProjectKeyFerryManager, VarlockError, never>;
5
+ export declare const projectKeyFerryManagerFactory: ProjectKeyFerryManagerFactory;
6
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/varlock/manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,KAAK,EAAoB,MAAM,QAAQ,CAAC;AACnE,OAAO,EACL,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,KAAK,6BAA6B,EAIlC,YAAY,EACb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,OAAO,EAKR,MAAM,wBAAwB,CAAC;AAwUhC,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,6BAA6B,EACtC,YAAY,GAAE,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAe,GAC7D,KAAK,CAAC,KAAK,CAAC,sBAAsB,EAAE,YAAY,EAAE,KAAK,CAAC,CA0U1D;AAED,eAAO,MAAM,6BAA6B,EAAE,6BAE3C,CAAC"}