@bjorntech/key-ferry 0.1.8 → 0.1.9

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 (52) hide show
  1. package/README.md +79 -13
  2. package/SECURITY.md +20 -0
  3. package/dist/contracts.d.ts +23 -0
  4. package/dist/contracts.d.ts.map +1 -1
  5. package/dist/contracts.js.map +1 -1
  6. package/dist/options.d.ts +7 -0
  7. package/dist/options.d.ts.map +1 -1
  8. package/dist/options.js +28 -2
  9. package/dist/options.js.map +1 -1
  10. package/dist/plugin.d.ts +4 -0
  11. package/dist/plugin.d.ts.map +1 -1
  12. package/dist/plugin.js +33 -171
  13. package/dist/plugin.js.map +1 -1
  14. package/dist/project-config.d.ts +3 -0
  15. package/dist/project-config.d.ts.map +1 -0
  16. package/dist/project-config.js +3 -0
  17. package/dist/project-config.js.map +1 -0
  18. package/dist/rpc.d.ts +141 -6
  19. package/dist/rpc.d.ts.map +1 -1
  20. package/dist/rpc.js +117 -35
  21. package/dist/rpc.js.map +1 -1
  22. package/dist/scoped-config.d.ts +35 -0
  23. package/dist/scoped-config.d.ts.map +1 -0
  24. package/dist/scoped-config.js +224 -0
  25. package/dist/scoped-config.js.map +1 -0
  26. package/dist/scoped-controller.d.ts +40 -0
  27. package/dist/scoped-controller.d.ts.map +1 -0
  28. package/dist/scoped-controller.js +468 -0
  29. package/dist/scoped-controller.js.map +1 -0
  30. package/dist/scopes/controller-helpers.d.ts +47 -0
  31. package/dist/scopes/controller-helpers.d.ts.map +1 -0
  32. package/dist/scopes/controller-helpers.js +268 -0
  33. package/dist/scopes/controller-helpers.js.map +1 -0
  34. package/dist/scopes/controller-types.d.ts +22 -0
  35. package/dist/scopes/controller-types.d.ts.map +1 -0
  36. package/dist/scopes/controller-types.js +2 -0
  37. package/dist/scopes/controller-types.js.map +1 -0
  38. package/dist/tui.d.ts +31 -33
  39. package/dist/tui.d.ts.map +1 -1
  40. package/dist/tui.js +111 -35
  41. package/dist/tui.js.map +1 -1
  42. package/docs/architecture.md +27 -1
  43. package/docs/troubleshooting.md +26 -1
  44. package/examples/README.md +47 -0
  45. package/examples/global/.env.schema +6 -0
  46. package/examples/global/opencode.json +31 -0
  47. package/examples/project/.env.schema +6 -0
  48. package/examples/project/.opencode/key-ferry.jsonc +10 -0
  49. package/examples/project/opencode.json +11 -0
  50. package/examples/{opencode.jsonc → single-project/opencode.json} +17 -16
  51. package/package.json +4 -1
  52. /package/examples/{.env.schema → single-project/.env.schema} +0 -0
@@ -75,7 +75,7 @@ An object supports an explicit mapping:
75
75
 
76
76
  The MCP server must already exist in `mcp.servers` and must be `type: "local"`.
77
77
  Remote or missing servers are not silently routed. Replace the illustrative
78
- command in `examples/opencode.jsonc` with a real local MCP command before
78
+ command in `examples/single-project/opencode.json` with a real local MCP command before
79
79
  launching it; the example command is not an installed fixture.
80
80
 
81
81
  The server remains disabled when the sidecar is not ready, startup or refresh
@@ -212,3 +212,28 @@ That command is a gated synthetic compatibility check. The normal suite and
212
212
  live fixtures are separate verification layers; these commands do not certify
213
213
  production deployments, every external MCP provider, or a fully live OpenCode
214
214
  host/TUI session.
215
+
216
+ ## Global/project activation and readiness
217
+
218
+ A native plugin being active does not mean its broker is ready. During startup,
219
+ wait for the selected scope to report its ready phase; mapped servers remain
220
+ fail-closed while it is starting. A disabled integration does not register the
221
+ status RPC, so a status request returning 404 is expected rather than evidence
222
+ of a broken Varlock backend.
223
+
224
+ The generated RPC client already wraps input objects. Use `status({})` (and the
225
+ same shape for refresh/doctor), not a manually double-wrapped payload. A 400 or
226
+ 404 from a bad probe does not prove the broker failed. Check the reported phase,
227
+ wait for startup, then use explicit refresh or doctor for the selected active
228
+ group. Status is pure and does not re-authenticate. Refresh and doctor do not
229
+ activate an inactive or manual project; use `activateProject({})` first, or the
230
+ project TUI command.
231
+
232
+ Global and project groups are independent. A project file is eligible only when
233
+ the global `projectConfig.enabled` option is explicitly true. Global automatic
234
+ activation can be restricted to manual by the project file, but a project
235
+ cannot override a global manual policy. Project mappings never inherit the
236
+ global mapping set; duplicate names require explicit `overrides`, and unrelated
237
+ global servers continue unchanged. Review project repositories before enabling
238
+ automatic activation: this is an execution-policy convenience, not a sandbox or
239
+ provider-authentication boundary.
@@ -0,0 +1,47 @@
1
+ # Configuration examples
2
+
3
+ These examples use the public package name `@bjorntech/key-ferry` and synthetic
4
+ values only. They do not start an MCP server or contact a provider.
5
+
6
+ ## Primary setup: global plugin plus project MCPs
7
+
8
+ Use the `global/` and `project/` pair when installing Key Ferry once in the
9
+ user's global OpenCode configuration:
10
+
11
+ 1. Copy `global/opencode.json` into the user's native global configuration at
12
+ `~/.config/opencode/opencode.json` (a generic public user-home path, not a
13
+ repository-specific path). Keep unrelated settings. Set its
14
+ `projectDirectory` to the absolute path of the Varlock root chosen for the
15
+ global key set, and copy `global/.env.schema` there.
16
+ 2. Copy `project/opencode.json` to the project root as the native
17
+ `opencode.json`, and copy `project/.env.schema` to the separate project
18
+ Varlock root selected for `PROJECT_API_KEY`.
19
+ 3. Copy `project/.opencode/key-ferry.jsonc` to the project at that path. It
20
+ maps the project's existing MCP name to its project key; it is not another
21
+ plugin entry.
22
+
23
+ The global and project schemas and mappings are separate key sets. The native
24
+ project file defines MCPs only, while the global file installs the plugin and
25
+ its global MCP definition. The `global-mcp` and `project-mcp` names match the
26
+ maps in their corresponding files. The sample commands are placeholders and
27
+ must be replaced with real local commands before use. For remote servers,
28
+ keep the server's URL and proxy decorators aligned; this example does not
29
+ wire a remote backend automatically.
30
+
31
+ The global `projectDirectory` placeholder is intentionally generic. Replace it
32
+ with an absolute path selected by the user; do not commit a real local path or
33
+ credential.
34
+
35
+ ## Alternative: one intentionally project-configured plugin
36
+
37
+ `single-project/` is the supported legacy flat setup. Copy its native
38
+ `opencode.json` and `.env.schema` together into one project root. Use this
39
+ alternative only when intentionally configuring the plugin in that project;
40
+ do not combine it with an existing globally configured Key Ferry mapping,
41
+ because host plugin options replace one another. It is an alternative to the
42
+ primary global-plus-project pair, not an additional layer.
43
+
44
+ Both native `opencode.json` files are strict JSON for ordinary editors. The
45
+ Key Ferry project mapping remains JSONC because its loader supports comments;
46
+ its filename is intentionally `key-ferry.jsonc`. `.env.schema` comments are
47
+ Varlock semantic decorators and must remain intact.
@@ -0,0 +1,6 @@
1
+ # Synthetic global-root example only. Do not put a real credential here.
2
+ # @proxyConfig={egress="strict"}
3
+ # ---
4
+ # @proxy(domain="global.example.test")
5
+ # @placeholder=global-test-placeholder
6
+ GLOBAL_API_KEY=global-test-placeholder
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "plugins": [
4
+ {
5
+ "package": "@bjorntech/key-ferry",
6
+ "options": {
7
+ "enabled": true,
8
+ "projectDirectory": "/absolute/path/to/global-varlock-project",
9
+ "projectConfig": {
10
+ "enabled": true,
11
+ "activation": "auto",
12
+ "file": ".opencode/key-ferry.jsonc"
13
+ },
14
+ "requireStrictEgress": true,
15
+ "servers": {
16
+ "global-mcp": {
17
+ "env": ["GLOBAL_API_KEY"]
18
+ }
19
+ }
20
+ }
21
+ }
22
+ ],
23
+ "mcp": {
24
+ "servers": {
25
+ "global-mcp": {
26
+ "type": "local",
27
+ "command": ["node", "./path/to/your-global-mcp-server.mjs"]
28
+ }
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,6 @@
1
+ # Synthetic project-root example only. Do not put a real credential here.
2
+ # @proxyConfig={egress="strict"}
3
+ # ---
4
+ # @proxy(domain="project.example.test")
5
+ # @placeholder=project-test-placeholder
6
+ PROJECT_API_KEY=project-test-placeholder
@@ -0,0 +1,10 @@
1
+ {
2
+ // Copy this file to the project root at .opencode/key-ferry.jsonc.
3
+ // The project group is additive: it never imports global mappings.
4
+ "enabled": true,
5
+ "servers": {
6
+ "project-mcp": {
7
+ "env": ["PROJECT_API_KEY"],
8
+ },
9
+ },
10
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "mcp": {
4
+ "servers": {
5
+ "project-mcp": {
6
+ "type": "local",
7
+ "command": ["node", "./path/to/your-project-mcp-server.mjs"]
8
+ }
9
+ }
10
+ }
11
+ }
@@ -2,8 +2,6 @@
2
2
  "$schema": "https://opencode.ai/config.json",
3
3
  "plugins": [
4
4
  {
5
- // Merge this entry into your existing config; preserve unrelated
6
- // plugins and MCP servers.
7
5
  "package": "@bjorntech/key-ferry",
8
6
  "options": {
9
7
  "enabled": true,
@@ -14,31 +12,34 @@
14
12
  "requireStrictEgress": true,
15
13
  "servers": {
16
14
  "example-local-mcp": {
17
- "env": ["FAKE_API_KEY"],
15
+ "env": ["FAKE_API_KEY"]
18
16
  },
19
17
  "example-remote-mcp": {
20
18
  "remote": {
21
19
  "headers": {
22
- "Authorization": { "env": "REMOTE_API_KEY", "prefix": "Bearer " },
23
- "X-Tenant": "REMOTE_TENANT",
24
- },
25
- },
26
- },
27
- },
28
- },
29
- },
20
+ "Authorization": {
21
+ "env": "REMOTE_API_KEY",
22
+ "prefix": "Bearer "
23
+ },
24
+ "X-Tenant": "REMOTE_TENANT"
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
30
31
  ],
31
32
  "mcp": {
32
33
  "servers": {
33
34
  "example-local-mcp": {
34
35
  "type": "local",
35
- "command": ["node", "./path/to/your-mcp-server.mjs"],
36
+ "command": ["node", "./path/to/your-mcp-server.mjs"]
36
37
  },
37
38
  "example-remote-mcp": {
38
39
  "type": "remote",
39
40
  "url": "https://mcp.example.test/mcp",
40
- "oauth": false,
41
- },
42
- },
43
- },
41
+ "oauth": false
42
+ }
43
+ }
44
+ }
44
45
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@bjorntech/key-ferry",
4
- "version": "0.1.8",
4
+ "version": "0.1.9",
5
5
  "description": "Project-scoped Key Ferry integration for OpenCode V2",
6
6
  "keywords": [],
7
7
  "homepage": "https://github.com/bjorntech/key-ferry#readme",
@@ -75,6 +75,9 @@
75
75
  "prepack": "npm run build",
76
76
  "prepublishOnly": "npm run quality && npm run build"
77
77
  },
78
+ "dependencies": {
79
+ "jsonc-parser": "3.3.1"
80
+ },
78
81
  "devDependencies": {
79
82
  "@opencode/plugin": "2.0.30",
80
83
  "@types/istanbul-lib-coverage": "2.0.6",