warpmetal 0.8.8 → 0.8.10
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/README.md +76 -35
- package/package.json +2 -2
- package/skills/warpmetal/SKILL.md +40 -15
- package/skills/warpmetal/references/cli-reference.md +40 -12
- package/skills/warpmetal/references/payments.md +7 -3
- package/skills/warpmetal/references/runtime.md +87 -35
- package/src/cli.js +83 -22
- package/src/installer.js +5 -90
- package/src/ssh-alias.js +726 -0
package/README.md
CHANGED
|
@@ -156,11 +156,15 @@ receipt finality while provisioning or renewal proceeds.
|
|
|
156
156
|
|
|
157
157
|
For an interactive initial purchase, `checkout challenge` may also return a
|
|
158
158
|
short-lived `humanCheckout` object. Its `url` and `qrPayload` are the same
|
|
159
|
-
`https://pay.x402api.com/c/...` bearer capability for the exact charge
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
159
|
+
`https://pay.x402api.com/c/...` bearer capability for the exact charge.
|
|
160
|
+
Present the exact URL as a clickable x402api handoff. If a QR is useful for
|
|
161
|
+
another device, encode only the identical `qrPayload` and explain that
|
|
162
|
+
scanning opens the hosted checkout without authorizing payment. x402api owns
|
|
163
|
+
any wallet selection or wallet-specific opening QR inside that page; never
|
|
164
|
+
synthesize a wallet link or encode the WarpMetal recipient address. The buyer
|
|
165
|
+
needs only the advertised USDC/USDT balance because x402api sponsors the native
|
|
166
|
+
gas. This is an alternative to the agent-wallet workflow, not a second
|
|
167
|
+
payment. After browser payment, run the exact
|
|
164
168
|
`humanCheckout.afterPayment.argv` status command. When the ready result asks
|
|
165
169
|
for `ask_human_for_notification_email`, ask the owner and add the optional
|
|
166
170
|
lifecycle-notification address they provide. Autonomous purchases and renewals
|
|
@@ -363,42 +367,79 @@ warpmetal sandbox access keygen \
|
|
|
363
367
|
--json
|
|
364
368
|
```
|
|
365
369
|
|
|
366
|
-
|
|
367
|
-
`hostKeyTrust.state: "trusted_first_use"` and the safe Ed25519 fingerprint.
|
|
368
|
-
Later installs report `"matched"`. First-use trust protects continuity after
|
|
369
|
-
that observation, but it cannot detect an active attacker on the first
|
|
370
|
-
connection. Provider-console host-key pre-enrollment remains an optional
|
|
371
|
-
higher-assurance alternative when it is available.
|
|
370
|
+
### Install a standard sandbox SSH alias
|
|
372
371
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
Bubblewrap PID namespace and private `/proc`:
|
|
372
|
+
Use a separate keypair and access grant for each sandbox. After the grant is
|
|
373
|
+
`applied`, install its token-free profile as a concrete OpenSSH alias:
|
|
376
374
|
|
|
377
375
|
```sh
|
|
378
|
-
warpmetal
|
|
379
|
-
--
|
|
380
|
-
--
|
|
381
|
-
--
|
|
382
|
-
--nested-private-procfs enable \
|
|
383
|
-
--wait \
|
|
376
|
+
warpmetal sandbox access install-ssh \
|
|
377
|
+
--connection-file <profile-path> \
|
|
378
|
+
--identity <sandbox-private-key-path> \
|
|
379
|
+
--alias <alias> \
|
|
384
380
|
--json
|
|
381
|
+
|
|
382
|
+
ssh <alias>
|
|
383
|
+
ssh -t <alias> codex
|
|
384
|
+
ssh <alias> codex exec '<task>'
|
|
385
|
+
ssh -t <alias> claude
|
|
386
|
+
ssh <alias> claude -p '<task>'
|
|
387
|
+
ssh -t <alias> agent
|
|
388
|
+
ssh <alias> agent -p '<task>'
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Install and authenticate Codex, Claude Code, or Cursor CLI inside the
|
|
392
|
+
sandbox first. Provider credentials are sandbox-owned and remain in its
|
|
393
|
+
persistent home; WarpMetal does not install these tools, perform their login,
|
|
394
|
+
or receive their credentials.
|
|
395
|
+
|
|
396
|
+
The alias is local-only. It prepends a managed include to `~/.ssh/config` and
|
|
397
|
+
uses the profile's pinned host key plus the sandbox identity. It never uses or
|
|
398
|
+
exposes the VPS owner management key. The server-side forced gateway maps that
|
|
399
|
+
identity to only its assigned sandbox, cannot open a host shell, and retains
|
|
400
|
+
`ClearAllForwardings yes` together with agent and X11 forwarding denial.
|
|
401
|
+
|
|
402
|
+
An exact reinstall is safe and unchanged. If an authenticated access refresh
|
|
403
|
+
produces a new profile, refresh the profile first and then explicitly replace
|
|
404
|
+
the local alias:
|
|
405
|
+
|
|
406
|
+
```sh
|
|
407
|
+
warpmetal sandbox access refresh \
|
|
408
|
+
--server <serverId> --sandbox <sandboxId> --grant <grantId> \
|
|
409
|
+
--connection-file <profile-path> --confirm REFRESH --wait --json
|
|
410
|
+
warpmetal sandbox access install-ssh \
|
|
411
|
+
--connection-file <profile-path> \
|
|
412
|
+
--identity <sandbox-private-key-path> \
|
|
413
|
+
--alias <alias> --confirm REFRESH --json
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
Remove only that managed alias and pin with explicit confirmation; unrelated
|
|
417
|
+
SSH configuration is preserved:
|
|
418
|
+
|
|
419
|
+
```sh
|
|
420
|
+
warpmetal sandbox access remove-ssh --alias <alias> --confirm REMOVE --json
|
|
385
421
|
```
|
|
386
422
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
423
|
+
[Codex Desktop's remote-connections contract](https://learn.chatgpt.com/docs/remote-connections)
|
|
424
|
+
discovers concrete aliases from `~/.ssh/config`, requires `ssh <alias>` to
|
|
425
|
+
work, and starts the remote app server through the login shell. Install Codex
|
|
426
|
+
inside the sandbox and ensure Codex is on the login-shell `PATH` before choosing
|
|
427
|
+
the alias in Codex Desktop.
|
|
428
|
+
|
|
429
|
+
The tested Cursor Remote SSH path is incompatible with this boundary because
|
|
430
|
+
it requests dynamic forwarding, which WarpMetal deliberately denies. Do not
|
|
431
|
+
weaken sandbox forwarding controls to make the IDE connect. Use the supported
|
|
432
|
+
[Cursor CLI](https://cursor.com/docs/cli/overview) interactively with
|
|
433
|
+
`ssh -t <alias> agent` or in
|
|
434
|
+
[headless mode](https://cursor.com/docs/cli/headless) with
|
|
435
|
+
`ssh <alias> agent -p '<task>'` instead.
|
|
436
|
+
|
|
437
|
+
On the first install in a server trust epoch, JSON output includes
|
|
438
|
+
`hostKeyTrust.state: "trusted_first_use"` and the safe Ed25519 fingerprint.
|
|
439
|
+
Later installs report `"matched"`. First-use trust protects continuity after
|
|
440
|
+
that observation, but it cannot detect an active attacker on the first
|
|
441
|
+
connection. Provider-console host-key pre-enrollment remains an optional
|
|
442
|
+
higher-assurance alternative when it is available.
|
|
402
443
|
|
|
403
444
|
Installation gives pre-existing Docker containers exact liveness checks and
|
|
404
445
|
tracks common container-runtime processes without collecting application
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "warpmetal",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.10",
|
|
4
4
|
"description": "Agent-safe CLI and skill for purchasing, renewing, and managing WarpMetal VPS servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"node": ">=20.0.0"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
|
-
"check": "node --check bin/warpmetal.js && node --check src/api.js && node --check src/args.js && node --check src/cli.js && node --check src/connection.js && node --check src/errors.js && node --check src/host-trust.js && node --check src/install-skill.js && node --check src/installer.js && node --check src/payment.js && node --check src/runtime.js && node --check src/ssh.js && node --check src/state.js && node --check src/version.js",
|
|
19
|
+
"check": "node --check bin/warpmetal.js && node --check src/api.js && node --check src/args.js && node --check src/cli.js && node --check src/connection.js && node --check src/errors.js && node --check src/host-trust.js && node --check src/install-skill.js && node --check src/installer.js && node --check src/payment.js && node --check src/runtime.js && node --check src/ssh-alias.js && node --check src/ssh.js && node --check src/state.js && node --check src/version.js",
|
|
20
20
|
"plugin:check": "node --test test/plugin.test.js",
|
|
21
21
|
"test": "node --test",
|
|
22
22
|
"prepack": "npm run check && npm test"
|
|
@@ -90,11 +90,14 @@ open either file.
|
|
|
90
90
|
|
|
91
91
|
In an interactive initial purchase, the result may also contain
|
|
92
92
|
`humanCheckout`. Offer it as an alternative to the local agent wallet. Show
|
|
93
|
-
`humanCheckout.url` as clickable text
|
|
94
|
-
`humanCheckout.qrPayload` URL as
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
`humanCheckout.url` as clickable x402api text. If another-device acquisition
|
|
94
|
+
is useful, render only the identical `humanCheckout.qrPayload` URL as a QR and
|
|
95
|
+
explain that scanning opens the hosted checkout without authorizing payment.
|
|
96
|
+
x402api owns any wallet selection and wallet-specific opening QR inside that
|
|
97
|
+
page; never synthesize a wallet link or render the recipient address as this
|
|
98
|
+
QR. The URL is an expiring bearer capability, so do not log, save, or send it
|
|
99
|
+
anywhere except to the buyer who requested this purchase. If the buyer uses it,
|
|
100
|
+
do not authorize or submit through the agent wallet. Run the
|
|
98
101
|
exact `humanCheckout.afterPayment.argv` command, wait for the server to become
|
|
99
102
|
ready, then follow `ask_human_for_notification_email`: ask the owner for the
|
|
100
103
|
optional lifecycle-notification address and add only the address they provide.
|
|
@@ -293,16 +296,6 @@ must match. Explain that TOFU cannot detect an active attacker on the first
|
|
|
293
296
|
connection; never use `ssh-keyscan`, accept a mismatch, or expose a generic pin
|
|
294
297
|
reset.
|
|
295
298
|
|
|
296
|
-
For any verified workload that creates an inner Bubblewrap PID namespace and
|
|
297
|
-
private `/proc`, CLI 0.8.7 with Runtime 0.1.25 or newer may add
|
|
298
|
-
`--nested-private-procfs enable` to the approved Runtime install. Planning with
|
|
299
|
-
a read-only checkout, coding in one writable checkout, and independent QA are
|
|
300
|
-
common uses. GitHub access, an AI CLI, or subagent delegation alone does not
|
|
301
|
-
require it. Omission means `preserve`, which leaves policy state unchanged;
|
|
302
|
-
`disable` is an explicit maintenance action. The exception is host-scoped
|
|
303
|
-
rather than sandbox-scoped, so separate workloads onto different VPS hosts when
|
|
304
|
-
they must not share it.
|
|
305
|
-
|
|
306
299
|
Omitted lifetime means persistent. A temporary sandbox requires
|
|
307
300
|
`--confirm TEMPORARY`, expires 15 minutes to 24 hours after first reaching
|
|
308
301
|
running, and permanently deletes its workspace at expiry. Never describe a
|
|
@@ -314,6 +307,38 @@ pinned host keys, then connect only through `warpmetal sandbox connect`.
|
|
|
314
307
|
Never give an agent the owner host key, owner token, SSH-derived management
|
|
315
308
|
token, runtime bootstrap, or node token.
|
|
316
309
|
|
|
310
|
+
CLI 0.8.10 or newer can turn the already-applied token-free profile into a
|
|
311
|
+
standard concrete OpenSSH alias. Read [references/runtime.md](references/runtime.md)
|
|
312
|
+
before installing one. Use a separate keypair and grant for each sandbox, and
|
|
313
|
+
pass the sandbox identity—not the VPS owner management key:
|
|
314
|
+
|
|
315
|
+
```sh
|
|
316
|
+
warpmetal sandbox access install-ssh \
|
|
317
|
+
--connection-file <profile-path> \
|
|
318
|
+
--identity <sandbox-private-key-path> \
|
|
319
|
+
--alias <alias> --json
|
|
320
|
+
ssh <alias>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
The local alias preserves the forced gateway: it cannot open a host shell and
|
|
324
|
+
does not relax forwarding denial. Provider authentication and credentials stay
|
|
325
|
+
inside the sandbox. After an authenticated profile refresh, update the alias
|
|
326
|
+
only with the explicit second confirmation:
|
|
327
|
+
|
|
328
|
+
```sh
|
|
329
|
+
warpmetal sandbox access refresh \
|
|
330
|
+
--server <serverId> --sandbox <sandboxId> --grant <grantId> \
|
|
331
|
+
--connection-file <profile-path> --confirm REFRESH --wait --json
|
|
332
|
+
warpmetal sandbox access install-ssh \
|
|
333
|
+
--connection-file <profile-path> \
|
|
334
|
+
--identity <sandbox-private-key-path> \
|
|
335
|
+
--alias <alias> --confirm REFRESH --json
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Remove it only with
|
|
339
|
+
`warpmetal sandbox access remove-ssh --alias <alias> --confirm REMOVE --json`.
|
|
340
|
+
Do not edit the generated fragment or host pin manually.
|
|
341
|
+
|
|
317
342
|
If the installed CLI lacks a required runtime command, stop, explain the
|
|
318
343
|
version limitation, and ask before upgrading the official npm package. Do not
|
|
319
344
|
reconstruct runtime changes with raw HTTP, ad hoc SSH, Podman, Docker, or host
|
|
@@ -75,8 +75,11 @@ workflow.
|
|
|
75
75
|
For interactive initial purchases, the response may additionally include
|
|
76
76
|
`humanCheckout.url`, the identical `qrPayload`, `expiresAt`, and an exact
|
|
77
77
|
`afterPayment.argv` command. The URL is a short-lived bearer capability for the
|
|
78
|
-
same charge, not a recipient address.
|
|
79
|
-
|
|
78
|
+
same charge, not a recipient address. Present the URL as a clickable x402api
|
|
79
|
+
handoff. An optional QR contains that exact web link for another-device
|
|
80
|
+
acquisition; scanning it does not authorize payment, and x402api owns any
|
|
81
|
+
wallet-specific choices inside the hosted page. If the buyer pays there, do not
|
|
82
|
+
submit an agent-wallet artifact; run the returned status command and,
|
|
80
83
|
after ready, follow `ask_human_for_notification_email` to offer lifecycle
|
|
81
84
|
notices. The CLI does not persist the hosted URL. Renewal commands never expose
|
|
82
85
|
or use this interactive option.
|
|
@@ -213,7 +216,6 @@ warpmetal runtime get --server <serverId> [--wait] [--timeout-seconds <n>] --jso
|
|
|
213
216
|
warpmetal runtime install \
|
|
214
217
|
--server <serverId> [--identity <owner-key>] --ssh-user root \
|
|
215
218
|
--confirm INSTALL \
|
|
216
|
-
[--nested-private-procfs <preserve|enable|disable>] \
|
|
217
219
|
[--wait] [--timeout-seconds <n>] --json
|
|
218
220
|
|
|
219
221
|
warpmetal sandbox create \
|
|
@@ -242,15 +244,6 @@ SCP operation is strict; changed keys, malformed pins, and failed or ambiguous
|
|
|
242
244
|
reloads never replace trust. This TOFU step cannot detect an active attacker on
|
|
243
245
|
the first connection. Provider-console pre-enrollment is optional and stronger.
|
|
244
246
|
|
|
245
|
-
The nested-private-procfs action requires CLI 0.8.7 and Runtime 0.1.25 or
|
|
246
|
-
newer. It defaults to `preserve`. `enable` is a host-level opt-in for any
|
|
247
|
-
verified workload that creates an inner Bubblewrap PID namespace and private
|
|
248
|
-
`/proc`; read-only planning, single-workspace coding, and independent QA are
|
|
249
|
-
common examples. GitHub use, an AI CLI, or subagent delegation alone does not
|
|
250
|
-
require it. `disable` unloads WarpMetal's policy and restores the recorded
|
|
251
|
-
pre-enable state. It is not a per-sandbox capability because Runtime sandboxes
|
|
252
|
-
share one Unix owner.
|
|
253
|
-
|
|
254
247
|
See [runtime.md](runtime.md) for capacity, lifetime, cleanup, polling, and
|
|
255
248
|
installation safety. Exit 8 means accepted or pending, never applied.
|
|
256
249
|
|
|
@@ -268,6 +261,10 @@ warpmetal sandbox access get \
|
|
|
268
261
|
warpmetal sandbox access refresh \
|
|
269
262
|
--server <serverId> --sandbox <sandboxId> --grant <grantId> \
|
|
270
263
|
--connection-file <profile-path> --confirm REFRESH [--wait] --json
|
|
264
|
+
warpmetal sandbox access install-ssh \
|
|
265
|
+
--connection-file <profile-path> --identity <sandbox-private-key-path> \
|
|
266
|
+
--alias <alias> [--confirm REFRESH] --json
|
|
267
|
+
warpmetal sandbox access remove-ssh --alias <alias> --confirm REMOVE --json
|
|
271
268
|
warpmetal sandbox access revoke \
|
|
272
269
|
--server <serverId> --sandbox <sandboxId> --grant <grantId> \
|
|
273
270
|
--confirm REVOKE [--wait] --json
|
|
@@ -282,6 +279,37 @@ creation requires `--wait`.
|
|
|
282
279
|
the currently applied grant and API-reported pinned host keys; use it after an
|
|
283
280
|
OS reload and supervisor reinstall.
|
|
284
281
|
|
|
282
|
+
`sandbox access install-ssh` is local-only and requires CLI 0.8.10 or newer.
|
|
283
|
+
It turns the reviewed profile and sandbox-private identity into a concrete
|
|
284
|
+
alias in `~/.ssh/config`. Exact replay is unchanged. If the profile, endpoint,
|
|
285
|
+
pin, or identity changes, first run the authenticated `sandbox access refresh`
|
|
286
|
+
command above, then repeat `sandbox access install-ssh ... --confirm REFRESH`.
|
|
287
|
+
Removal requires exact `--confirm REMOVE` and preserves unrelated SSH config.
|
|
288
|
+
|
|
289
|
+
Use a separate keypair and grant for each sandbox. The alias never uses or
|
|
290
|
+
exposes the VPS owner management key; the forced gateway cannot open a host
|
|
291
|
+
shell, and forwarding remains disabled with `ClearAllForwardings yes`.
|
|
292
|
+
Authentication for user-installed tools happens inside the sandbox. Common
|
|
293
|
+
interactive and one-shot entry points are:
|
|
294
|
+
|
|
295
|
+
```sh
|
|
296
|
+
ssh <alias>
|
|
297
|
+
ssh -t <alias> codex
|
|
298
|
+
ssh <alias> codex exec '<task>'
|
|
299
|
+
ssh -t <alias> claude
|
|
300
|
+
ssh <alias> claude -p '<task>'
|
|
301
|
+
ssh -t <alias> agent
|
|
302
|
+
ssh <alias> agent -p '<task>'
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
[Codex Desktop](https://learn.chatgpt.com/docs/remote-connections) reads
|
|
306
|
+
the concrete alias from `~/.ssh/config` and starts Codex through the sandbox
|
|
307
|
+
login shell, so Codex must be installed and on that login-shell `PATH`. The
|
|
308
|
+
tested Cursor Remote SSH route requests prohibited dynamic forwarding and is
|
|
309
|
+
not compatible with this boundary. Keep forwarding denied and use the
|
|
310
|
+
[Cursor CLI](https://cursor.com/docs/cli/overview) interactive or
|
|
311
|
+
[headless](https://cursor.com/docs/cli/headless) commands shown above.
|
|
312
|
+
|
|
285
313
|
## Skill installation and state
|
|
286
314
|
|
|
287
315
|
```sh
|
|
@@ -125,9 +125,13 @@ argv arrays returned under `paymentWorkflow`:
|
|
|
125
125
|
|
|
126
126
|
For an interactive initial purchase, an optional `humanCheckout` object offers
|
|
127
127
|
a second presentation path for the same charge. Its `url` and `qrPayload` must
|
|
128
|
-
be identical hosted-checkout URLs
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
be identical hosted-checkout URLs. Present `url` as the clickable x402api
|
|
129
|
+
handoff. If a QR is useful for another device, render only the exact
|
|
130
|
+
`qrPayload` and explain that scanning opens the checkout without authorizing
|
|
131
|
+
payment. x402api owns wallet selection and any wallet-specific opening QR
|
|
132
|
+
inside that page; never synthesize a wallet link or render a recipient address.
|
|
133
|
+
If the buyer completes this path, skip agent-wallet authorization and run
|
|
134
|
+
`humanCheckout.afterPayment.argv`. Continue bounded
|
|
131
135
|
status polling until ready, then ask for the optional lifecycle-notification
|
|
132
136
|
email when the result returns `ask_human_for_notification_email`. The hosted
|
|
133
137
|
URL expires at `humanCheckout.expiresAt`, is not persisted by the CLI, and is
|
|
@@ -58,7 +58,6 @@ warpmetal runtime install \
|
|
|
58
58
|
--identity <owner-private-key-path> \
|
|
59
59
|
--ssh-user root \
|
|
60
60
|
--confirm INSTALL \
|
|
61
|
-
[--nested-private-procfs <preserve|enable|disable>] \
|
|
62
61
|
--wait \
|
|
63
62
|
--json
|
|
64
63
|
warpmetal runtime get --server <serverId> --wait --json
|
|
@@ -81,29 +80,6 @@ is an optional higher-assurance alternative, not a requirement. Only a locally
|
|
|
81
80
|
recorded successful reload that reports an owner-host-key refresh creates one
|
|
82
81
|
new operation-bound trust epoch; failed or ambiguous reloads do not.
|
|
83
82
|
|
|
84
|
-
`--nested-private-procfs` is supported by `warpmetal` CLI 0.8.7 with Agent
|
|
85
|
-
Runtime 0.1.25 or newer. Its default is `preserve`, which makes no AppArmor
|
|
86
|
-
policy change. Select `enable` only when this VPS is intentionally dedicated to
|
|
87
|
-
a verified workload that creates an inner Bubblewrap PID namespace and private
|
|
88
|
-
procfs. Ordinary VPS users and Runtime workloads that rely only on the outer
|
|
89
|
-
sandbox do not need it. Select `disable` only during an approved maintenance
|
|
90
|
-
action to unload WarpMetal's policy and restore the exact file and loaded-policy
|
|
91
|
-
state that existed before enablement.
|
|
92
|
-
|
|
93
|
-
Examples include a planner with an exact read-only checkout, a coder with only
|
|
94
|
-
one approved checkout and output directory writable, and QA with an exact
|
|
95
|
-
candidate plus isolated test processes and scratch space. This protects a
|
|
96
|
-
persistent trusted runner from repository-controlled commands and sibling
|
|
97
|
-
attempts. GitHub access, installing an AI CLI, and subagent delegation alone do
|
|
98
|
-
not require nested private procfs.
|
|
99
|
-
|
|
100
|
-
This setting is host-scoped, not sandbox-scoped. Runtime sandboxes share one
|
|
101
|
-
Unix owner, so every sandbox on the host can use the exception only through the
|
|
102
|
-
signed, root-owned, fixed bwrap path matched by the policy. Enabling it does not
|
|
103
|
-
authorize arbitrary bwrap binaries or change the trust boundary for the
|
|
104
|
-
Runtime image selected by WarpMetal's authenticated backend. Isolate workloads
|
|
105
|
-
on separate VPS hosts if they must not share this host capability.
|
|
106
|
-
|
|
107
83
|
The signed installer is designed to preserve container workloads already
|
|
108
84
|
running on a supported host. It selects `crun` for WarpMetal's private rootless
|
|
109
85
|
Podman service, refuses APT removals and DNF erasures, protects installed
|
|
@@ -128,17 +104,6 @@ host automatically:
|
|
|
128
104
|
unexpectedly; stop and review the host package logs;
|
|
129
105
|
- `runtime_legacy_migration_required`: preview Podman state needs a separate,
|
|
130
106
|
explicitly reviewed migration and was not reset.
|
|
131
|
-
- `runtime_nested_private_procfs_architecture_unsupported`: the requested
|
|
132
|
-
coding-host policy is unsupported by this CPU architecture;
|
|
133
|
-
- `runtime_apparmor_state_unverifiable`: the host's current AppArmor state
|
|
134
|
-
cannot be established safely;
|
|
135
|
-
- `runtime_apparmor_policy_conflict`: an existing file or loaded-policy state
|
|
136
|
-
conflicts with WarpMetal's recorded transaction;
|
|
137
|
-
- `runtime_apparmor_policy_rollback_failed`: the installer could not restore
|
|
138
|
-
the exact prior AppArmor state; stop and perform operator recovery.
|
|
139
|
-
- `runtime_apparmor_policy_recovery_failed`: an interrupted prior policy
|
|
140
|
-
transaction could not be recovered; stop and perform operator recovery.
|
|
141
|
-
|
|
142
107
|
There is no force bypass. If `runtime_reboot_required` is returned, schedule
|
|
143
108
|
the reboot as a separate maintenance action and retry only after the host and
|
|
144
109
|
its existing workloads are healthy. The ordinary installer never installs a
|
|
@@ -262,6 +227,93 @@ The sandbox record is retained, but its old workspace is not; reconciliation
|
|
|
262
227
|
creates a new empty workspace. Never bypass a host-key mismatch or reuse the
|
|
263
228
|
pre-reload profile.
|
|
264
229
|
|
|
230
|
+
### Install a concrete OpenSSH alias
|
|
231
|
+
|
|
232
|
+
CLI 0.8.10 or newer can install the reviewed profile as a standard local alias
|
|
233
|
+
without another API request:
|
|
234
|
+
|
|
235
|
+
```sh
|
|
236
|
+
warpmetal sandbox access install-ssh \
|
|
237
|
+
--connection-file <profile-path> \
|
|
238
|
+
--identity <sandbox-private-key-path> \
|
|
239
|
+
--alias <alias> \
|
|
240
|
+
--json
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Use a separate keypair and grant for each sandbox. The identity must be the
|
|
244
|
+
private half of that sandbox grant, never the VPS owner management key. The
|
|
245
|
+
command validates the closed token-free profile and its fingerprints, then
|
|
246
|
+
prepends a managed include to `~/.ssh/config`. It writes a private alias
|
|
247
|
+
fragment and dedicated pinned known-hosts file. Exact reinstall is idempotent.
|
|
248
|
+
|
|
249
|
+
If an authenticated access refresh changes the profile, endpoint, host pin, or
|
|
250
|
+
identity, run the server-backed profile refresh first and then explicitly
|
|
251
|
+
replace the local alias:
|
|
252
|
+
|
|
253
|
+
```sh
|
|
254
|
+
warpmetal sandbox access refresh \
|
|
255
|
+
--server <serverId> \
|
|
256
|
+
--sandbox <sandboxId> \
|
|
257
|
+
--grant <grantId> \
|
|
258
|
+
--connection-file <profile-path> \
|
|
259
|
+
--confirm REFRESH \
|
|
260
|
+
--wait \
|
|
261
|
+
--json
|
|
262
|
+
warpmetal sandbox access install-ssh \
|
|
263
|
+
--connection-file <profile-path> \
|
|
264
|
+
--identity <sandbox-private-key-path> \
|
|
265
|
+
--alias <alias> \
|
|
266
|
+
--confirm REFRESH \
|
|
267
|
+
--json
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Never replace a pin merely because an SSH connection reports a mismatch. The
|
|
271
|
+
alias installer consumes only the already-refreshed API profile and does not
|
|
272
|
+
scan or trust a network key. Remove one alias without changing unrelated SSH
|
|
273
|
+
configuration:
|
|
274
|
+
|
|
275
|
+
```sh
|
|
276
|
+
warpmetal sandbox access remove-ssh --alias <alias> --confirm REMOVE --json
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The generated host block pins the exact host keys, selects only the sandbox
|
|
280
|
+
identity, disables password and keyboard-interactive authentication, retains
|
|
281
|
+
`ClearAllForwardings yes`, disables agent/X11 forwarding and local commands,
|
|
282
|
+
and contains neither `RemoteCommand` nor `RequestTTY`. The existing server-side
|
|
283
|
+
forced gateway still maps the key to exactly one sandbox. The alias cannot open
|
|
284
|
+
a host shell and never uses or exposes the owner management key.
|
|
285
|
+
|
|
286
|
+
After installing and authenticating each provider tool inside the sandbox, use
|
|
287
|
+
the alias for interactive or one-shot work:
|
|
288
|
+
|
|
289
|
+
```sh
|
|
290
|
+
ssh <alias>
|
|
291
|
+
ssh -t <alias> codex
|
|
292
|
+
ssh <alias> codex exec '<task>'
|
|
293
|
+
ssh -t <alias> claude
|
|
294
|
+
ssh <alias> claude -p '<task>'
|
|
295
|
+
ssh -t <alias> agent
|
|
296
|
+
ssh <alias> agent -p '<task>'
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Provider authentication and credentials are sandbox-owned and persist only in
|
|
300
|
+
the sandbox home. WarpMetal does not install, authenticate, configure, or
|
|
301
|
+
receive credentials for Codex, Claude Code, or Cursor CLI.
|
|
302
|
+
|
|
303
|
+
[Codex Desktop](https://learn.chatgpt.com/docs/remote-connections)
|
|
304
|
+
discovers a concrete alias through `~/.ssh/config`, requires ordinary
|
|
305
|
+
`ssh <alias>` connectivity, and launches the remote app server through the
|
|
306
|
+
login shell. Codex must therefore be installed inside the sandbox and on the
|
|
307
|
+
login-shell `PATH` before selecting the alias in Codex Desktop.
|
|
308
|
+
|
|
309
|
+
The tested Cursor Remote SSH path requests dynamic forwarding, which the
|
|
310
|
+
Runtime correctly denies, so Cursor IDE remote access is not supported by this
|
|
311
|
+
restricted alias. Do not relax forwarding controls. Use the official
|
|
312
|
+
[Cursor CLI](https://cursor.com/docs/cli/overview) interactively with
|
|
313
|
+
`ssh -t <alias> agent` or in
|
|
314
|
+
[headless mode](https://cursor.com/docs/cli/headless) with
|
|
315
|
+
`ssh <alias> agent -p '<task>'` instead.
|
|
316
|
+
|
|
265
317
|
Connect without an owner management credential:
|
|
266
318
|
|
|
267
319
|
```sh
|