@easonwumac/computer-linker 0.1.2

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 (82) hide show
  1. package/CHANGELOG.md +230 -0
  2. package/LICENSE +21 -0
  3. package/README.md +539 -0
  4. package/SECURITY.md +48 -0
  5. package/dist/api.d.ts +2 -0
  6. package/dist/api.js +360 -0
  7. package/dist/audit.d.ts +70 -0
  8. package/dist/audit.js +102 -0
  9. package/dist/capabilities.d.ts +98 -0
  10. package/dist/capabilities.js +718 -0
  11. package/dist/capability-policy.d.ts +22 -0
  12. package/dist/capability-policy.js +103 -0
  13. package/dist/chatgpt.d.ts +167 -0
  14. package/dist/chatgpt.js +561 -0
  15. package/dist/cli.d.ts +2 -0
  16. package/dist/cli.js +4621 -0
  17. package/dist/client-smoke.d.ts +44 -0
  18. package/dist/client-smoke.js +639 -0
  19. package/dist/client.d.ts +217 -0
  20. package/dist/client.js +357 -0
  21. package/dist/codex-runs.d.ts +35 -0
  22. package/dist/codex-runs.js +66 -0
  23. package/dist/computer-contract.d.ts +33 -0
  24. package/dist/computer-contract.js +384 -0
  25. package/dist/computer-operation-registry.d.ts +45 -0
  26. package/dist/computer-operation-registry.js +179 -0
  27. package/dist/config-diagnostics.d.ts +11 -0
  28. package/dist/config-diagnostics.js +185 -0
  29. package/dist/config.d.ts +10 -0
  30. package/dist/config.js +69 -0
  31. package/dist/history-insights.d.ts +132 -0
  32. package/dist/history-insights.js +457 -0
  33. package/dist/http-auth.d.ts +3 -0
  34. package/dist/http-auth.js +15 -0
  35. package/dist/mcp-surface.d.ts +5 -0
  36. package/dist/mcp-surface.js +25 -0
  37. package/dist/oauth-provider.d.ts +52 -0
  38. package/dist/oauth-provider.js +325 -0
  39. package/dist/package-metadata.d.ts +7 -0
  40. package/dist/package-metadata.js +24 -0
  41. package/dist/permissions.d.ts +43 -0
  42. package/dist/permissions.js +150 -0
  43. package/dist/platform-shell.d.ts +28 -0
  44. package/dist/platform-shell.js +124 -0
  45. package/dist/processes.d.ts +50 -0
  46. package/dist/processes.js +178 -0
  47. package/dist/profile.d.ts +159 -0
  48. package/dist/profile.js +416 -0
  49. package/dist/screenshot.d.ts +47 -0
  50. package/dist/screenshot.js +302 -0
  51. package/dist/search.d.ts +34 -0
  52. package/dist/search.js +340 -0
  53. package/dist/security.d.ts +10 -0
  54. package/dist/security.js +108 -0
  55. package/dist/sensitive-files.d.ts +4 -0
  56. package/dist/sensitive-files.js +96 -0
  57. package/dist/server.d.ts +9 -0
  58. package/dist/server.js +713 -0
  59. package/dist/service.d.ts +125 -0
  60. package/dist/service.js +486 -0
  61. package/dist/sessions.d.ts +26 -0
  62. package/dist/sessions.js +34 -0
  63. package/dist/tunnels.d.ts +161 -0
  64. package/dist/tunnels.js +1243 -0
  65. package/dist/workspace-operations.d.ts +170 -0
  66. package/dist/workspace-operations.js +3219 -0
  67. package/dist/workspaces.d.ts +61 -0
  68. package/dist/workspaces.js +353 -0
  69. package/docs/agent-instructions.md +65 -0
  70. package/docs/alpha-evidence.example.json +54 -0
  71. package/docs/api-compatibility.md +56 -0
  72. package/docs/architecture.md +561 -0
  73. package/docs/chatgpt-setup.md +397 -0
  74. package/docs/client-recipes.md +98 -0
  75. package/docs/client-sdk.md +163 -0
  76. package/docs/computer-operation-v1.schema.json +143 -0
  77. package/docs/manual-test-plan.md +322 -0
  78. package/docs/product-spec.md +911 -0
  79. package/docs/release-checklist.md +285 -0
  80. package/docs/service-mode.md +99 -0
  81. package/examples/minimal-mcp-client.mjs +114 -0
  82. package/package.json +87 -0
@@ -0,0 +1,143 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/easonwumac/computer-linker/schemas/computer-operation-v1.schema.json",
4
+ "title": "Computer Linker computer_operation v1",
5
+ "description": "Stable request and result envelope for Computer Linker computer_operation.",
6
+ "type": "object",
7
+ "required": ["request", "result"],
8
+ "properties": {
9
+ "request": {
10
+ "$ref": "#/$defs/ComputerOperationRequest"
11
+ },
12
+ "result": {
13
+ "oneOf": [
14
+ { "$ref": "#/$defs/ComputerOperationSuccess" },
15
+ { "$ref": "#/$defs/ComputerOperationFailure" }
16
+ ]
17
+ }
18
+ },
19
+ "$defs": {
20
+ "JsonObject": {
21
+ "type": "object",
22
+ "additionalProperties": true
23
+ },
24
+ "ComputerOperationRequest": {
25
+ "type": "object",
26
+ "additionalProperties": false,
27
+ "required": ["scope", "op"],
28
+ "properties": {
29
+ "scope": {
30
+ "type": "string",
31
+ "minLength": 1,
32
+ "description": "Configured scope id or name."
33
+ },
34
+ "op": {
35
+ "type": "string",
36
+ "minLength": 1,
37
+ "description": "Stable dotted operation name such as code.context, file.read, git.diff, package.run, command.run, codex.run, or history.last."
38
+ },
39
+ "target": {
40
+ "type": "string",
41
+ "description": "Primary operation target, such as a path, process id, command working directory, display id, or session id."
42
+ },
43
+ "input": {
44
+ "$ref": "#/$defs/JsonObject",
45
+ "default": {}
46
+ },
47
+ "options": {
48
+ "$ref": "#/$defs/JsonObject",
49
+ "default": {}
50
+ }
51
+ }
52
+ },
53
+ "ComputerOperationSuccess": {
54
+ "type": "object",
55
+ "additionalProperties": false,
56
+ "required": ["ok", "operationId", "scope", "op", "startedAt", "durationMs", "data"],
57
+ "properties": {
58
+ "ok": { "const": true },
59
+ "operationId": {
60
+ "type": "string",
61
+ "pattern": "^op_[0-9a-fA-F-]{36}$"
62
+ },
63
+ "scope": { "type": "string" },
64
+ "op": { "type": "string" },
65
+ "startedAt": {
66
+ "type": "string",
67
+ "format": "date-time"
68
+ },
69
+ "durationMs": {
70
+ "type": "integer",
71
+ "minimum": 0
72
+ },
73
+ "data": true,
74
+ "warnings": {
75
+ "type": "array",
76
+ "items": { "type": "string" },
77
+ "default": []
78
+ }
79
+ }
80
+ },
81
+ "ComputerOperationFailure": {
82
+ "type": "object",
83
+ "additionalProperties": false,
84
+ "required": ["ok", "operationId", "scope", "op", "startedAt", "durationMs", "error"],
85
+ "properties": {
86
+ "ok": { "const": false },
87
+ "operationId": {
88
+ "type": "string",
89
+ "pattern": "^op_[0-9a-fA-F-]{36}$"
90
+ },
91
+ "scope": { "type": "string" },
92
+ "op": { "type": "string" },
93
+ "startedAt": {
94
+ "type": "string",
95
+ "format": "date-time"
96
+ },
97
+ "durationMs": {
98
+ "type": "integer",
99
+ "minimum": 0
100
+ },
101
+ "error": {
102
+ "$ref": "#/$defs/ComputerOperationError"
103
+ },
104
+ "warnings": {
105
+ "type": "array",
106
+ "items": { "type": "string" },
107
+ "default": []
108
+ }
109
+ }
110
+ },
111
+ "ComputerOperationError": {
112
+ "type": "object",
113
+ "additionalProperties": false,
114
+ "required": ["code", "message", "retryable"],
115
+ "properties": {
116
+ "code": {
117
+ "enum": [
118
+ "invalid_request",
119
+ "unknown_scope",
120
+ "unknown_operation",
121
+ "permission_denied",
122
+ "path_out_of_scope",
123
+ "unsupported_platform",
124
+ "provider_unavailable",
125
+ "timeout",
126
+ "process_not_found",
127
+ "os_permission_required",
128
+ "execution_failed"
129
+ ]
130
+ },
131
+ "message": {
132
+ "type": "string"
133
+ },
134
+ "retryable": {
135
+ "type": "boolean"
136
+ },
137
+ "details": {
138
+ "$ref": "#/$defs/JsonObject"
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
@@ -0,0 +1,322 @@
1
+ # Manual Test Plan
2
+
3
+ Use this plan before sharing an alpha build or when dogfooding a local
4
+ checkout. It keeps the first test isolated from your real Computer Linker
5
+ config.
6
+
7
+ Commands below assume this checkout and use `npm run dev --`. When testing an
8
+ installed package instead, replace `npm run dev --` with `computer-linker`.
9
+
10
+ ## 1. Build Gate
11
+
12
+ ```bash
13
+ npm ci
14
+ npm run product:check
15
+ npm run alpha:check
16
+ npm run public:mirror -- --dry-run --remote <github-owner>/<public-repo>
17
+ npm run dev -- self-test
18
+ ```
19
+
20
+ Expected:
21
+
22
+ - typecheck, tests, build, release validation, and package smoke pass
23
+ - package smoke reports `computer-linker-<version>.tgz` and verifies a
24
+ temporary consumer install, installed CLI execution, installed self-test,
25
+ isolated setup/status, and SDK import
26
+ - alpha readiness reports `status: ready`, or `status: needs_attention` only
27
+ because preserved Git history must be published through `public:mirror`
28
+ - `public:mirror -- --dry-run --remote ...` reports the mirror dry-run is
29
+ publishable when the fresh public mirror path is accepted and the other gates
30
+ pass; before a real mirror release, resolve any `release tag check: blocked
31
+ for real run` changelog warning
32
+ - `self-test` reports `ready: yes` and verifies the local MCP SDK tool flow
33
+ without touching real user workspaces
34
+ - external MCP client/tunnel evidence is still pending until the later tunnel
35
+ smoke step writes `.computer-linker-alpha-evidence.json`
36
+
37
+ ## 2. Isolated Local Config
38
+
39
+ Use a disposable config directory for the first manual pass.
40
+
41
+ PowerShell:
42
+
43
+ ```powershell
44
+ $env:COMPUTER_LINKER_CONFIG_DIR = "$PWD\.computer-linker-test\config"
45
+ npm run dev -- setup . --id app --url https://mcp.example.com --show-token
46
+ npm run dev -- status
47
+ npm run dev -- doctor --fix --dry-run
48
+ npm run dev -- doctor --fix
49
+ npm run dev -- config validate
50
+ ```
51
+
52
+ Bash:
53
+
54
+ ```bash
55
+ export COMPUTER_LINKER_CONFIG_DIR="$PWD/.computer-linker-test/config"
56
+ npm run dev -- setup . --id app --url https://mcp.example.com --show-token
57
+ npm run dev -- status
58
+ npm run dev -- doctor --fix --dry-run
59
+ npm run dev -- doctor --fix
60
+ npm run dev -- config validate
61
+ ```
62
+
63
+ Expected:
64
+
65
+ - `config validate` does not report `blocked`
66
+ - `workspace list` shows the `app` scope named from the checkout folder
67
+ - first-run `setup` / `start <folder>` does not leave the bootstrap `current`
68
+ scope in the config
69
+ - `status` says `doctor --fix` removes the bootstrap `current` scope instead
70
+ of implying it will only add an execution policy
71
+ - new workspaces are read-only unless you explicitly add `--write`
72
+ - shell remains disabled unless you explicitly add `--shell`
73
+ - `--shell` or `--codex` adds a default execution policy with `allowedCommands`,
74
+ `maxRuntimeSeconds`, and `maxOutputBytes`
75
+ - `doctor --fix --dry-run` reports planned repairs without writing the config
76
+ - `doctor --fix` is idempotent and reports `changed: no` on a second run
77
+ - duplicate folder scopes with different permissions are reported for manual
78
+ cleanup without recommending one specific id to remove
79
+ - setup output includes `public access: MCP endpoint only`, a concise
80
+ connection summary, and the next start/client setup commands. Full WAF and
81
+ policy details stay in `setup --json`.
82
+
83
+ Tailscale Funnel variant:
84
+
85
+ ```powershell
86
+ npm run dev -- start C:\Projects\my-app --tunnel tailscale
87
+ ```
88
+
89
+ Expected:
90
+
91
+ - start auto-creates the config, owner token, and workspace entry
92
+ - start prints `server: running` and `startup check: ready` after verifying
93
+ local HTTP, JSON API, and MCP tool flow
94
+ - start does not require a `https://*.ts.net` URL
95
+ - start prints `tunnel: tailscale active`, `public MCP:`, and
96
+ `saved public URL:`
97
+ - `config show` contains the detected `https://<machine>.<tailnet>.ts.net`
98
+ origin after start
99
+
100
+ OpenAI Secure MCP Tunnel variant:
101
+
102
+ ```powershell
103
+ $env:CONTROL_PLANE_API_KEY = "sk-..."
104
+ npm run dev -- start C:\Projects\my-app --tunnel openai --tunnel-id tunnel_...
105
+ ```
106
+
107
+ Expected:
108
+
109
+ - start auto-creates the config, owner token, and workspace entry
110
+ - start prints `server: running` and `startup check: ready`
111
+ - first start downloads OpenAI's official `tunnel-client` into
112
+ `~/.computer-linker/tools/openai-tunnel-client/`
113
+ - start prints `connect: OpenAI Tunnel mode`, `tunnel: OpenAI Secure MCP
114
+ Tunnel active`, and `tunnel id:`
115
+ - start tells the user that ChatGPT Tunnel mode uses the tunnel id and should
116
+ not receive a pasted bearer token
117
+ - no `publicBaseUrl` is required or saved for this mode
118
+ - `status` and `doctor` do not ask for `publicBaseUrl` while an OpenAI Secure
119
+ MCP Tunnel is active
120
+
121
+ ## 3. HTTP, CLI, And API
122
+
123
+ Terminal A:
124
+
125
+ ```bash
126
+ npm run dev -- start . --id app
127
+ ```
128
+
129
+ Terminal B:
130
+
131
+ ```bash
132
+ npm run dev -- doctor
133
+ npm run dev -- status
134
+ npm run dev -- self-test
135
+ npm run dev -- profile
136
+ npm run dev -- client setup
137
+ npm run dev -- client setup --details
138
+ npm run dev -- client setup --show-token
139
+ npm run dev -- client setup --json
140
+ npm run dev -- diagnose client
141
+ npm run dev -- client smoke --url http://127.0.0.1:3939/mcp --allow-http
142
+ COMPUTER_LINKER_TOKEN=<ownerToken> node examples/minimal-mcp-client.mjs
143
+ npm run dev -- process list app
144
+ npm run dev -- screen status
145
+ npm run dev -- history --view last
146
+ ```
147
+
148
+ Expected:
149
+
150
+ - `/healthz`, authenticated `/api/v1/capabilities`, `get_computer_info`,
151
+ read-only `computer_operation` `file.list`, and local MCP SDK smoke pass
152
+ - `status` shows machine identity, local MCP URL, public MCP/tunnel state,
153
+ workspace count, warnings, and next actions
154
+ - `doctor` shows full diagnostics, security findings, history commands, and
155
+ setup guidance
156
+ - `client setup` reports a short generic MCP connection summary without
157
+ requiring ChatGPT-specific profile formats; `client setup --details` prints
158
+ tool names, first prompt, and agent instructions; `--show-token` prints the
159
+ bearer header only when explicitly requested on a trusted screen
160
+ - `diagnose client` reports setup readiness, MCP smoke result, connection
161
+ history count, blockers, and next actions
162
+ - `examples/minimal-mcp-client.mjs` can initialize `/mcp`, list tools, call
163
+ `get_computer_info`, run read-only `computer_operation`, and read history
164
+ - `process list` reports currently managed background command/Codex processes
165
+ or `none` while the local HTTP server is running
166
+ - `screen status` reports provider support, permission status, and
167
+ screen-enabled workspaces without capturing pixels
168
+ - On Windows, primary-display capture is available through the PowerShell
169
+ screenshot provider in an interactive desktop session. Test actual capture
170
+ only with a `--screen` workspace and only when local screen contents are safe
171
+ to capture.
172
+ - security warnings are understandable and match the configured permissions
173
+
174
+ ## 4. JSON API Contract
175
+
176
+ Use the owner token returned on a trusted local setup screen by:
177
+
178
+ ```bash
179
+ npm run dev -- profile --show-token
180
+ npm run dev -- setup . --id app --show-token
181
+ npm run dev -- config token rotate --show-token
182
+ ```
183
+
184
+ Then call:
185
+
186
+ ```bash
187
+ curl -s -H "Authorization: Bearer <ownerToken>" http://127.0.0.1:3939/api/v1/capabilities
188
+ ```
189
+
190
+ Generic operation smoke:
191
+
192
+ ```bash
193
+ curl -s -H "Authorization: Bearer <ownerToken>" \
194
+ -H "content-type: application/json" \
195
+ -d "{\"action\":\"computer_operation\",\"scope\":\"app\",\"op\":\"file.search\",\"target\":\".\",\"input\":{\"query\":\"Computer Linker\",\"glob\":\"README.md\"},\"options\":{\"maxResults\":5}}" \
196
+ http://127.0.0.1:3939/api/v1/control
197
+ ```
198
+
199
+ Expected:
200
+
201
+ - capabilities includes `computerOperationContract` and
202
+ `computerOperationRegistry`
203
+ - `computer_operation` returns `{ "ok": true, ... }` with an `operationId`
204
+ - path and permission failures return a structured `{ "ok": false, "error": ... }`
205
+ envelope
206
+
207
+ ## 5. MCP Client Smoke
208
+
209
+ For a local MCP client, use:
210
+
211
+ ```text
212
+ http://127.0.0.1:3939/mcp
213
+ ```
214
+
215
+ Expected tool flow:
216
+
217
+ 1. `get_computer_info`
218
+ 2. `computer_operation` with `scope: "app"` and `op: "file.search"`
219
+ 3. `get_operation_history`
220
+
221
+ The built-in `client smoke` command already verifies a bounded version of this
222
+ through the MCP SDK: initialize, tools/list, `get_computer_info`, and
223
+ read-only `computer_operation` `file.list`. Keep this manual step for at least
224
+ one external MCP client before announcing a public alpha.
225
+
226
+ Compatibility clients may still use the older MCP surface after starting with
227
+ `COMPUTER_LINKER_MCP_TOOL_SURFACE=compatibility`:
228
+
229
+ 1. `get_capabilities`
230
+ 2. `list_workspaces`
231
+ 3. `open_workspace`
232
+ 4. `workspace_operation`
233
+
234
+ ## 6. Tunnel Smoke
235
+
236
+ Only run this after local HTTP smoke passes and an owner token is configured.
237
+
238
+ ```bash
239
+ npm run dev -- client chatgpt verify --mode coding
240
+ npm run dev -- start
241
+ ```
242
+
243
+ Or:
244
+
245
+ ```powershell
246
+ npm run dev -- start C:\Projects\my-app --tunnel tailscale
247
+ ```
248
+
249
+ Or:
250
+
251
+ ```powershell
252
+ $env:CONTROL_PLANE_API_KEY = "sk-..."
253
+ npm run dev -- start C:\Projects\my-app --tunnel openai --tunnel-id tunnel_...
254
+ ```
255
+
256
+ Expected:
257
+
258
+ - start refuses to open a tunnel if no owner token is configured
259
+ - public URL modes: `client chatgpt url` reports a public HTTPS MCP URL
260
+ - OpenAI tunnel mode: ChatGPT connector settings use Tunnel plus the
261
+ `tunnel_...` id instead of a public URL
262
+ - public `client smoke --url <https-origin>/mcp` passes without `--allow-http`
263
+ using MCP-only SDK checks; it must not require public `/api/v1` access
264
+
265
+ After one real external MCP client has called `get_computer_info`,
266
+ `computer_operation`, and `get_operation_history`, record the smoke pass
267
+ without hand-editing JSON:
268
+
269
+ ```bash
270
+ npm run alpha:evidence -- preflight
271
+ npm run alpha:evidence -- smoke --redaction-confirmed
272
+ npm run alpha:check -- --require-evidence
273
+ ```
274
+
275
+ `preflight` reads local config, audit history, and tunnel runtime state. Use it
276
+ to confirm the history contains the external tool flow before recording
277
+ evidence; it also prints a read-only prompt to paste into the external MCP
278
+ client. When only one call is missing, `nextExternalClientPrompt` contains a
279
+ short prompt for that missing call. When the preflight no longer fails, run the
280
+ printed `recordCommand`. `smoke` auto-detects the exposure, tunnel target, and
281
+ scope from local preflight state when possible. It does not write the evidence
282
+ file until you run `smoke` and confirm redaction with `--redaction-confirmed`.
283
+ If an older Computer Linker alpha evidence file already exists, `smoke`
284
+ refreshes it for the current test; unrelated files still require `--force`
285
+ before replacement.
286
+
287
+ Use `npm run alpha:evidence -- init` plus `record-smoke` or `record` only when
288
+ you want to split the steps or keep separate notes per required check.
289
+
290
+ Expected:
291
+
292
+ - evidence check passes for the current package version and Git HEAD
293
+ - evidence is no older than 14 days
294
+ - exposure is OpenAI, Cloudflare, Tailscale Funnel, or a manual reverse proxy
295
+ - OpenAI evidence records the tested `tunnel_...` id; public URL provider
296
+ evidence records an HTTPS origin or URL
297
+ - target MCP path is `/mcp`, and target scope records the workspace scope used
298
+ by the external test
299
+ - public alpha evidence confirms `/mcp` works and `/api/v1` / `/healthz` are
300
+ not exposed through the public surface
301
+ - `alpha:evidence init` and `record` refuse common secret-shaped values before
302
+ writing the evidence file
303
+ - evidence does not contain owner tokens, API keys, bearer headers,
304
+ screenshots, or private file contents
305
+
306
+ ## Cleanup
307
+
308
+ Stop the HTTP server with `Ctrl+C`.
309
+
310
+ PowerShell:
311
+
312
+ ```powershell
313
+ Remove-Item -Recurse -Force .computer-linker-test
314
+ Remove-Item Env:\COMPUTER_LINKER_CONFIG_DIR
315
+ ```
316
+
317
+ Bash:
318
+
319
+ ```bash
320
+ rm -rf .computer-linker-test
321
+ unset COMPUTER_LINKER_CONFIG_DIR
322
+ ```