@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
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Release checklist
|
|
2
|
+
|
|
3
|
+
This is a maintainer runbook. Nothing in this document performs a release,
|
|
4
|
+
changes repository settings, creates a tag, pushes code, or publishes to npm.
|
|
5
|
+
Do not put npm credentials or long-lived publish tokens in the repository or in
|
|
6
|
+
chat.
|
|
7
|
+
|
|
8
|
+
## One-time account and repository setup
|
|
9
|
+
|
|
10
|
+
Complete these steps interactively, using an account that owns the
|
|
11
|
+
`@bjorntech` scope and has publish permission. Verify the scope ownership,
|
|
12
|
+
account/org access, and 2FA before continuing.
|
|
13
|
+
|
|
14
|
+
1. Decide whether the repository should be public. npm provenance for this
|
|
15
|
+
package requires the public repository/package policy used by this project;
|
|
16
|
+
in GitHub, use **Settings → General → Danger Zone → Change visibility** and
|
|
17
|
+
make the repository public if that is the approved decision. This is a
|
|
18
|
+
manual decision, not an automated release step.
|
|
19
|
+
2. Create the GitHub environment named exactly `production`. Configure its
|
|
20
|
+
required reviewers (do not enable self-review if that would defeat the
|
|
21
|
+
approval policy), and restrict deployments to the approved stable version
|
|
22
|
+
tag pattern (`v*`). Protect tag creation and `main` with the repository's
|
|
23
|
+
normal branch/ruleset policy.
|
|
24
|
+
3. Push the release workflow and its supporting release scripts to `main`
|
|
25
|
+
before configuring npm Trusted Publishing. The fixed workflow filename is
|
|
26
|
+
`.github/workflows/publish.yml`.
|
|
27
|
+
4. Bootstrap the package if it does not yet exist on npm. For the initial
|
|
28
|
+
`0.1.0` release, run the normal quality/build gates below, then use one
|
|
29
|
+
interactive browser/2FA login and publish from the repository:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm login
|
|
33
|
+
npm publish --access public
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Do not add `--provenance` to this local bootstrap publish. This initial
|
|
37
|
+
publication does not validate OIDC, and `0.1.0` must not be tagged and
|
|
38
|
+
published again after it already exists.
|
|
39
|
+
5. Shortly before the next genuine release, configure npm Trusted Publishing
|
|
40
|
+
for the package at **Package settings → Trusted Publisher** with:
|
|
41
|
+
- provider: **GitHub Actions**
|
|
42
|
+
- organization/owner: `bjorntech`
|
|
43
|
+
- repository: `key-ferry`
|
|
44
|
+
- workflow filename: `publish.yml`
|
|
45
|
+
- environment: `production`
|
|
46
|
+
|
|
47
|
+
Use npm's current UI field names if they differ. A newly created,
|
|
48
|
+
unvalidated configuration expires after 48 hours without a successful
|
|
49
|
+
publish, so do not create a fake release merely to test it. Configure it
|
|
50
|
+
for the next real version (for example, `0.1.1`) after the bootstrap
|
|
51
|
+
package exists. See [npm Trusted Publishers](https://docs.npmjs.com/trusted-publishers/)
|
|
52
|
+
and the [npm trust command reference](https://docs.npmjs.com/cli/v12/commands/npm-trust).
|
|
53
|
+
6. After the first successful OIDC release, consider enabling npm's **Require
|
|
54
|
+
two-factor authentication** and **Disallow tokens** package controls, and
|
|
55
|
+
lock down classic publishing as allowed by the account policy. Trusted
|
|
56
|
+
publishing uses the GitHub OIDC exchange; it does not require an
|
|
57
|
+
`NPM_TOKEN`, `NODE_AUTH_TOKEN`, or another repository secret.
|
|
58
|
+
|
|
59
|
+
## Quality gates
|
|
60
|
+
|
|
61
|
+
From the repository root, run the normal gates before committing a release:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
bun install --frozen-lockfile
|
|
65
|
+
bun run format:check
|
|
66
|
+
bun typecheck
|
|
67
|
+
bun test
|
|
68
|
+
bun run test:coverage
|
|
69
|
+
bun run test:crap
|
|
70
|
+
bun run build
|
|
71
|
+
bun pm pack --dry-run
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The coverage gate requires aggregate runtime-source coverage of at least 90%
|
|
75
|
+
for lines and 75% for functions. The CRAP gate requires new or changed
|
|
76
|
+
functions to score at most 6; unchanged legacy violations warn, while
|
|
77
|
+
regressions against the committed baseline fail. Review the reports rather
|
|
78
|
+
than hard-coding their current counts.
|
|
79
|
+
|
|
80
|
+
Run the two opt-in Varlock fixtures separately with a configured CLI path and
|
|
81
|
+
synthetic isolated fixtures:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
VARLOCK_LIVE_BINARY=/absolute/path/to/varlock bun test tests/varlock-live.test.ts
|
|
85
|
+
VARLOCK_LIVE_BINARY=/absolute/path/to/varlock bun test tests/remote-varlock-live.test.ts
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
These fixtures do not substitute for production deployment or compatibility
|
|
89
|
+
testing with every external MCP service.
|
|
90
|
+
|
|
91
|
+
## Release and tag flow
|
|
92
|
+
|
|
93
|
+
1. Review the package version, changelog, exports, generated package contents,
|
|
94
|
+
public-scope permissions, repository visibility, and the complete release
|
|
95
|
+
diff. Set a new, genuine semver version; never retry a version that npm has
|
|
96
|
+
already accepted. Update the lockfile consistently and rerun all gates.
|
|
97
|
+
2. Commit the reviewed source and workflow changes, push the selected branch,
|
|
98
|
+
and wait for the commit to be available on `main`.
|
|
99
|
+
3. Create and push the matching stable tag only after explicit approval:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
git tag vX.Y.Z
|
|
103
|
+
git push origin vX.Y.Z
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The tag must point at the reviewed release commit and its version must
|
|
107
|
+
match `package.json` exactly. Stable tags are the only automatic publish
|
|
108
|
+
trigger; the workflow does not publish from `main`.
|
|
109
|
+
4. `.github/workflows/publish.yml` runs on GitHub-hosted Ubuntu with the
|
|
110
|
+
pinned Node 24.22/npm 12.2/Bun 1.4.2 toolchain and verified action SHA
|
|
111
|
+
pins. Its unprivileged `verify` job has contents-read permission, runs the
|
|
112
|
+
quality/build checks, and creates the tarball artifact. The privileged
|
|
113
|
+
`publish` job has contents-read and `id-token: write`, waits for the
|
|
114
|
+
`production` environment approval, and publishes **exactly the verified
|
|
115
|
+
tarball** with `--access public --provenance --ignore-scripts`.
|
|
116
|
+
|
|
117
|
+
The quality/build job is the gate: the publish job must not re-execute
|
|
118
|
+
source or dependency installation in a privileged context. The
|
|
119
|
+
`--ignore-scripts` flag is intentional for the final artifact publication,
|
|
120
|
+
not a way to bypass the quality gates.
|
|
121
|
+
5. For a manually started run, select an existing stable tag as the workflow
|
|
122
|
+
ref. For example:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
gh workflow run publish.yml --ref vX.Y.Z
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Do not dispatch from `main` or use an arbitrary branch. At the environment
|
|
129
|
+
approval, inspect the tag, commit, tarball, and checksum before approving.
|
|
130
|
+
After publication, verify the exact registry version, provenance, public
|
|
131
|
+
access, clean installation, and the documented OpenCode V2 plugin/TUI
|
|
132
|
+
discovery path.
|
|
133
|
+
|
|
134
|
+
## Troubleshooting
|
|
135
|
+
|
|
136
|
+
- **Package not found (404):** complete the one-time interactive bootstrap;
|
|
137
|
+
Trusted Publishing cannot create the first package.
|
|
138
|
+
- **OIDC token missing:** check that the publish job has exactly the runtime
|
|
139
|
+
`id-token: write` permission and that the environment name is exactly
|
|
140
|
+
`production`.
|
|
141
|
+
- **Provenance or repository failure:** verify the package is public, the
|
|
142
|
+
Trusted Publisher fields match `bjorntech/key-ferry` and `publish.yml`, and
|
|
143
|
+
the run is from a stable tag.
|
|
144
|
+
- **Configuration expired:** recreate it shortly before the next genuine
|
|
145
|
+
release; do not manufacture an empty or fake release.
|
|
146
|
+
- **Version already exists:** check the registry first, then increment to a
|
|
147
|
+
new genuine version. Do not blindly retry or attempt to overwrite it.
|
|
148
|
+
- **Quality failure:** fix the source and rerun the gates. Do not use
|
|
149
|
+
`--ignore-scripts` indiscriminately or bypass the verification job.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
This integration is a native OpenCode V2 Effect plugin. It manages an owned,
|
|
4
|
+
project-scoped Varlock CLI proxy process. Start OpenCode normally from the
|
|
5
|
+
project directory. Do not wrap OpenCode with `varlock proxy`.
|
|
6
|
+
|
|
7
|
+
## Before starting
|
|
8
|
+
|
|
9
|
+
Install Varlock CLI **1.23.0** separately and make sure `varlock` is on `PATH`:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
varlock --version
|
|
13
|
+
varlock proxy --help
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The plugin does not install Varlock, unlock secret stores, or read credentials
|
|
17
|
+
for diagnostics. It expects a valid `.env.schema` in the configured project.
|
|
18
|
+
Configure the Varlock environment, secret source, authentication, and proxy
|
|
19
|
+
rules before starting OpenCode, following the [Varlock documentation](https://varlock.dev/).
|
|
20
|
+
|
|
21
|
+
The integration protects explicitly mapped local MCP servers and selected
|
|
22
|
+
remote API-key MCP servers. Direct provider transports are not isolated.
|
|
23
|
+
Remote servers not selected by this plugin, including OAuth-only servers, keep
|
|
24
|
+
native OpenCode OAuth and transport behavior.
|
|
25
|
+
|
|
26
|
+
## Plugin does not load
|
|
27
|
+
|
|
28
|
+
Add `@bjorntech/key-ferry@0.1.0` to the OpenCode V2 `plugins` list and preserve
|
|
29
|
+
unrelated configuration. OpenCode installs configured npm plugins
|
|
30
|
+
automatically. Install Varlock separately, preferably with
|
|
31
|
+
`brew install dmno-dev/tap/varlock`.
|
|
32
|
+
|
|
33
|
+
Configure the server plugin from `opencode.json(c)`. OpenCode V2 discovers the
|
|
34
|
+
package's sibling `./tui` export automatically, so a duplicate global
|
|
35
|
+
`cli.json` entry is not needed. A global `cli.json` entry is optional only when
|
|
36
|
+
the CLI connects to a remote OpenCode server that already loaded the server
|
|
37
|
+
plugin, or for a genuinely CLI-only deployment. There is no project-local
|
|
38
|
+
`cli.json` setup.
|
|
39
|
+
|
|
40
|
+
The plugin requires OpenCode V2's native Effect entrypoint, compatible with
|
|
41
|
+
`@opencode/plugin` 2.0.30 and Effect 4.0.1. Do not load it through the Promise
|
|
42
|
+
entrypoint. The package declares Node >=22; Bun 1.4.2 is used by this project
|
|
43
|
+
for development and CI.
|
|
44
|
+
|
|
45
|
+
If OpenCode reports a plugin import or entrypoint error, check the built
|
|
46
|
+
package exports and restart the OpenCode service after rebuilding.
|
|
47
|
+
|
|
48
|
+
Relative `projectDirectory` values are resolved against OpenCode's project
|
|
49
|
+
directory and canonicalized before the sidecar starts. The resulting canonical
|
|
50
|
+
directory is used for Varlock ownership matching and safe status output.
|
|
51
|
+
|
|
52
|
+
## MCP server is disabled
|
|
53
|
+
|
|
54
|
+
The plugin changes only names listed in `options.servers`. Each mapping is
|
|
55
|
+
output environment name to an exact Varlock placeholder name. An array is a
|
|
56
|
+
same-name mapping:
|
|
57
|
+
|
|
58
|
+
```jsonc
|
|
59
|
+
"servers": {
|
|
60
|
+
"example-local-mcp": {
|
|
61
|
+
"env": ["FAKE_API_KEY"]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
An object supports an explicit mapping:
|
|
67
|
+
|
|
68
|
+
```jsonc
|
|
69
|
+
"servers": {
|
|
70
|
+
"example-local-mcp": {
|
|
71
|
+
"env": { "UPSTREAM_KEY": "FAKE_API_KEY" }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The MCP server must already exist in `mcp.servers` and must be `type: "local"`.
|
|
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
|
|
79
|
+
launching it; the example command is not an installed fixture.
|
|
80
|
+
|
|
81
|
+
The server remains disabled when the sidecar is not ready, startup or refresh
|
|
82
|
+
fails, a mapped placeholder is absent, or the project explicitly disabled the
|
|
83
|
+
server. This is fail-closed behavior. A later successful refresh can restore a
|
|
84
|
+
server that the plugin disabled, but never one explicitly disabled in project
|
|
85
|
+
configuration.
|
|
86
|
+
|
|
87
|
+
## Remote MCP server is disabled
|
|
88
|
+
|
|
89
|
+
Select a remote server with a `remote.headers` mapping only when the native
|
|
90
|
+
MCP configuration explicitly uses `oauth: false`:
|
|
91
|
+
|
|
92
|
+
```jsonc
|
|
93
|
+
{
|
|
94
|
+
"type": "remote",
|
|
95
|
+
"url": "https://mcp.example.test/mcp",
|
|
96
|
+
"oauth": false
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The plugin then creates an authenticated loopback relay. Header mappings refer
|
|
101
|
+
to exact Varlock environment names, not raw values:
|
|
102
|
+
|
|
103
|
+
```jsonc
|
|
104
|
+
"remote-tools": {
|
|
105
|
+
"remote": {
|
|
106
|
+
"headers": {
|
|
107
|
+
"Authorization": { "env": "REMOTE_API_KEY", "prefix": "Bearer " },
|
|
108
|
+
"X-Tenant": "REMOTE_TENANT"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
If `oauth` is omitted or is an OAuth object, the selected server is disabled
|
|
115
|
+
with a safe diagnostic. Remove the mapping to preserve native OAuth, or
|
|
116
|
+
explicitly choose API-key mode with `oauth: false`. The plugin never silently
|
|
117
|
+
disables OAuth or falls back to the direct remote URL.
|
|
118
|
+
|
|
119
|
+
The remote URL must be HTTPS without URL credentials or a fragment. Literal
|
|
120
|
+
loopback, private, link-local, and metadata IP targets are rejected unless
|
|
121
|
+
`allowPrivateNetwork: true` is explicitly configured. Corporate DNS names are
|
|
122
|
+
allowed. The relay target is fixed from the configured server and cannot be
|
|
123
|
+
chosen by a downstream MCP request.
|
|
124
|
+
|
|
125
|
+
The relay supports Streamable HTTP and legacy SSE, including streaming,
|
|
126
|
+
session headers, DELETE termination, cancellation, and same-origin legacy SSE
|
|
127
|
+
endpoint rewriting. It caps registered session routes at 256, rejects new
|
|
128
|
+
routes after the cap, and does not count duplicate registrations. A Varlock
|
|
129
|
+
refresh or relay replacement resets native MCP sessions. Existing sessions
|
|
130
|
+
must reconnect.
|
|
131
|
+
|
|
132
|
+
Verification status: the synthetic HTTPS remote Varlock test passes. This
|
|
133
|
+
does not claim compatibility with every external MCP provider or a live
|
|
134
|
+
OpenCode TUI session.
|
|
135
|
+
|
|
136
|
+
## Strict egress or schema errors
|
|
137
|
+
|
|
138
|
+
With `requireStrictEgress: true`, the manager requires the Varlock schema to
|
|
139
|
+
use strict egress. The schema header syntax is:
|
|
140
|
+
|
|
141
|
+
```env-spec
|
|
142
|
+
# @proxyConfig={egress="strict"}
|
|
143
|
+
# ---
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Route a protected item with an item decorator, for example:
|
|
147
|
+
|
|
148
|
+
```env-spec
|
|
149
|
+
# @proxy(domain="api.example.test")
|
|
150
|
+
FAKE_API_KEY=sk-test-000000000000000000000000
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`@proxy(domain=...)` on an item creates the injection rule. A header-level
|
|
154
|
+
proxy rule alone does not inject an item. Do not use a real key in examples or
|
|
155
|
+
diagnostics.
|
|
156
|
+
|
|
157
|
+
The plugin's protocol accepts only exact placeholder matches. `@proxy=passthrough`
|
|
158
|
+
values are allowed by Varlock for child environments, but they are not a
|
|
159
|
+
wildcard source for this integration and cannot satisfy an unrelated mapping.
|
|
160
|
+
|
|
161
|
+
## Proxy-aware SDK behavior
|
|
162
|
+
|
|
163
|
+
An explicitly mapped local MCP process receives proxy-related environment
|
|
164
|
+
wiring only when the proxy is ready. A local client that ignores or overwrites
|
|
165
|
+
those variables can bypass the intended route.
|
|
166
|
+
|
|
167
|
+
An explicitly mapped remote MCP server uses the authenticated relay instead of
|
|
168
|
+
native direct transport. The relay sends placeholder-bearing headers through
|
|
169
|
+
Varlock's HTTP CONNECT proxy to the fixed HTTPS target, so remote routing does
|
|
170
|
+
not depend on the MCP client honoring environment proxy variables. CA MITM
|
|
171
|
+
support and response scrubbing still have limitations. This integration is not
|
|
172
|
+
a sandbox and cannot isolate a same-user process from stores, files, or daemons.
|
|
173
|
+
|
|
174
|
+
## Refresh, status, and doctor
|
|
175
|
+
|
|
176
|
+
The server plugin exposes the `key-ferry` RPC with `status`, `refresh`,
|
|
177
|
+
and `doctor` methods. These return sanitized phase, project, generation, PID,
|
|
178
|
+
endpoint metadata, safe configuration diagnostics, and safe error codes. They
|
|
179
|
+
do not return environment maps, relay capabilities or tokens, CA material, or
|
|
180
|
+
secret values.
|
|
181
|
+
|
|
182
|
+
If refresh fails, protected servers are disabled and the failure is reported
|
|
183
|
+
as a sanitized `unavailable` RPC error. Doctor first ensures Varlock state and
|
|
184
|
+
then reconciles or recreates unhealthy selected `oauth:false` remote relays;
|
|
185
|
+
it does not silently authenticate or replace native OAuth. Check the Varlock
|
|
186
|
+
schema and configured authentication context, then use `/key-ferry-refresh` or
|
|
187
|
+
`/key-ferry-doctor`, or the matching Varlock palette commands, when the TUI is
|
|
188
|
+
available. Do not manually stop unrelated Varlock processes: only the process
|
|
189
|
+
owned by this project manager is eligible for cleanup.
|
|
190
|
+
|
|
191
|
+
## Verify the installation
|
|
192
|
+
|
|
193
|
+
These commands do not contact a real service or require credentials:
|
|
194
|
+
|
|
195
|
+
```sh
|
|
196
|
+
bun typecheck
|
|
197
|
+
bun test
|
|
198
|
+
bun run build
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
An opt-in live test is available with `VARLOCK_LIVE_BINARY` set to an absolute
|
|
202
|
+
Varlock CLI path. It uses a synthetic fixture and isolated XDG configuration.
|
|
203
|
+
Do not enable real secret-manager, OAuth, or network tests in CI.
|
|
204
|
+
|
|
205
|
+
The remote live fixture is gated and skipped by default:
|
|
206
|
+
|
|
207
|
+
```sh
|
|
208
|
+
VARLOCK_LIVE_BINARY=/absolute/path/to/varlock bun test tests/remote-varlock-live.test.ts
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
That command is a gated synthetic compatibility check. The normal suite and
|
|
212
|
+
live fixtures are separate verification layers; these commands do not certify
|
|
213
|
+
production deployments, every external MCP provider, or a fully live OpenCode
|
|
214
|
+
host/TUI session.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Synthetic example only. Do not put a real credential in this file.
|
|
2
|
+
# Strict egress blocks requests that do not match an explicit proxy rule.
|
|
3
|
+
# @proxyConfig={egress="strict"}
|
|
4
|
+
# ---
|
|
5
|
+
# @proxy(domain="api.example.test")
|
|
6
|
+
# @placeholder=sk-test-000000000000000000000000
|
|
7
|
+
FAKE_API_KEY=sk-test-000000000000000000000000
|
|
8
|
+
|
|
9
|
+
# Synthetic remote MCP API-key example. The value is deliberately fake.
|
|
10
|
+
# @proxy(domain="mcp.example.test")
|
|
11
|
+
# @placeholder=sk-remote-test-000000000000000000000
|
|
12
|
+
REMOTE_API_KEY=sk-remote-test-000000000000000000000
|
|
13
|
+
|
|
14
|
+
# This is also synthetic and is mapped as a header placeholder in the example.
|
|
15
|
+
# @proxy(domain="mcp.example.test")
|
|
16
|
+
# @placeholder=tenant-test-placeholder
|
|
17
|
+
REMOTE_TENANT=tenant-test-placeholder
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://opencode.ai/config.json",
|
|
3
|
+
"plugins": [
|
|
4
|
+
{
|
|
5
|
+
// Merge this entry into your existing config; preserve unrelated
|
|
6
|
+
// plugins and MCP servers.
|
|
7
|
+
"package": "@bjorntech/key-ferry@0.1.0",
|
|
8
|
+
"options": {
|
|
9
|
+
"enabled": true,
|
|
10
|
+
"projectDirectory": ".",
|
|
11
|
+
"command": ["varlock"],
|
|
12
|
+
"startupTimeoutMs": 30000,
|
|
13
|
+
"reloadTimeoutMs": 30000,
|
|
14
|
+
"requireStrictEgress": true,
|
|
15
|
+
"servers": {
|
|
16
|
+
"example-local-mcp": {
|
|
17
|
+
"env": ["FAKE_API_KEY"],
|
|
18
|
+
},
|
|
19
|
+
"example-remote-mcp": {
|
|
20
|
+
"remote": {
|
|
21
|
+
"headers": {
|
|
22
|
+
"Authorization": { "env": "REMOTE_API_KEY", "prefix": "Bearer " },
|
|
23
|
+
"X-Tenant": "REMOTE_TENANT",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
"mcp": {
|
|
32
|
+
"servers": {
|
|
33
|
+
"example-local-mcp": {
|
|
34
|
+
"type": "local",
|
|
35
|
+
"command": ["node", "./path/to/your-mcp-server.mjs"],
|
|
36
|
+
},
|
|
37
|
+
"example-remote-mcp": {
|
|
38
|
+
"type": "remote",
|
|
39
|
+
"url": "https://mcp.example.test/mcp",
|
|
40
|
+
"oauth": false,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,98 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package.json",
|
|
2
3
|
"name": "@bjorntech/key-ferry",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Project-scoped Key Ferry integration for OpenCode V2",
|
|
6
|
+
"keywords": [],
|
|
7
|
+
"homepage": "https://github.com/bjorntech/key-ferry#readme",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/bjorntech/key-ferry/issues"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/bjorntech/key-ferry.git"
|
|
16
|
+
},
|
|
17
|
+
"directories": {
|
|
18
|
+
"doc": "docs",
|
|
19
|
+
"example": "examples",
|
|
20
|
+
"test": "tests"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"SECURITY.md",
|
|
27
|
+
"docs",
|
|
28
|
+
"examples"
|
|
29
|
+
],
|
|
30
|
+
"type": "module",
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"import": "./dist/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./contracts": {
|
|
39
|
+
"types": "./dist/contracts.d.ts",
|
|
40
|
+
"import": "./dist/contracts.js"
|
|
41
|
+
},
|
|
42
|
+
"./plugin": {
|
|
43
|
+
"types": "./dist/plugin.d.ts",
|
|
44
|
+
"import": "./dist/plugin.js"
|
|
45
|
+
},
|
|
46
|
+
"./options": {
|
|
47
|
+
"types": "./dist/options.d.ts",
|
|
48
|
+
"import": "./dist/options.js"
|
|
49
|
+
},
|
|
50
|
+
"./rpc": {
|
|
51
|
+
"types": "./dist/rpc.d.ts",
|
|
52
|
+
"import": "./dist/rpc.js"
|
|
53
|
+
},
|
|
54
|
+
"./tui": {
|
|
55
|
+
"types": "./dist/tui.d.ts",
|
|
56
|
+
"import": "./dist/tui.js"
|
|
57
|
+
},
|
|
58
|
+
"./relay": {
|
|
59
|
+
"types": "./dist/relay/index.d.ts",
|
|
60
|
+
"import": "./dist/relay/index.js"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsc -p tsconfig.build.json",
|
|
68
|
+
"typecheck": "tsc --noEmit",
|
|
69
|
+
"test": "bun test",
|
|
70
|
+
"test:coverage": "bun test --coverage && bun scripts/check-coverage.ts",
|
|
71
|
+
"test:crap": "bun scripts/crap/run.ts",
|
|
72
|
+
"format": "oxfmt",
|
|
73
|
+
"format:check": "oxfmt --check",
|
|
74
|
+
"quality": "npm run format:check && npm run typecheck && npm run test:coverage && npm run test:crap",
|
|
75
|
+
"prepack": "npm run build",
|
|
76
|
+
"prepublishOnly": "npm run quality && npm run build"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@opencode/plugin": "2.0.30",
|
|
80
|
+
"@types/istanbul-lib-coverage": "2.0.6",
|
|
81
|
+
"@types/istanbul-lib-instrument": "1.7.8",
|
|
82
|
+
"@types/node": "^24.0.0",
|
|
83
|
+
"effect": "4.0.1",
|
|
84
|
+
"istanbul-lib-coverage": "3.2.2",
|
|
85
|
+
"istanbul-lib-instrument": "6.0.3",
|
|
86
|
+
"oxfmt": "0.72.0",
|
|
87
|
+
"solid-js": "1.9.17",
|
|
88
|
+
"typescript": "^5.8.2"
|
|
89
|
+
},
|
|
90
|
+
"peerDependencies": {
|
|
91
|
+
"@opencode/plugin": "2.0.30",
|
|
92
|
+
"effect": "4.0.1",
|
|
93
|
+
"solid-js": ">=1.9.0"
|
|
94
|
+
},
|
|
95
|
+
"engines": {
|
|
96
|
+
"node": ">=22"
|
|
97
|
+
}
|
|
98
|
+
}
|