@braedonsaunders/appkit-desk 0.7.0 → 0.8.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/README.md +55 -0
- package/backend.d.ts +28 -7
- package/backend.d.ts.map +1 -1
- package/backend.js +18 -521
- package/backend.js.map +1 -1
- package/host.d.ts +4 -1
- package/host.d.ts.map +1 -1
- package/host.js +31 -16
- package/host.js.map +1 -1
- package/index.d.ts +2 -0
- package/index.d.ts.map +1 -1
- package/index.js +2 -0
- package/index.js.map +1 -1
- package/machine.d.ts +145 -0
- package/machine.d.ts.map +1 -0
- package/machine.js +518 -0
- package/machine.js.map +1 -0
- package/package.json +2 -2
- package/plan.d.ts +129 -31
- package/plan.d.ts.map +1 -1
- package/plan.js +165 -9
- package/plan.js.map +1 -1
- package/port-relay.d.ts +13 -0
- package/port-relay.d.ts.map +1 -0
- package/port-relay.js +56 -0
- package/port-relay.js.map +1 -0
- package/virtualization.d.ts +16 -0
- package/virtualization.d.ts.map +1 -0
- package/virtualization.js +148 -0
- package/virtualization.js.map +1 -0
- package/vz/Package.swift +23 -0
- package/vz/Sources/DeskNet/Addresses.swift +106 -0
- package/vz/Sources/DeskNet/DHCP.swift +111 -0
- package/vz/Sources/DeskNet/Fence.swift +57 -0
- package/vz/Sources/DeskNet/NetworkStack.swift +547 -0
- package/vz/Sources/DeskNet/Packets.swift +355 -0
- package/vz/Sources/DeskNet/Plumbing.swift +312 -0
- package/vz/Sources/DeskNet/Sockets.swift +221 -0
- package/vz/Sources/DeskNet/TCPFlow.swift +448 -0
- package/vz/Sources/appkit-desk-vz/Control.swift +152 -0
- package/vz/Sources/appkit-desk-vz/Helper.swift +505 -0
- package/vz/Sources/appkit-desk-vz/main.swift +38 -0
- package/vz/Tests/DeskNetTests/DeskNetTests.swift +426 -0
- package/vz/appkit-desk-vz.entitlements +8 -0
- package/vz/build.sh +23 -0
- package/vz/check/extract-boot.py +221 -0
package/README.md
CHANGED
|
@@ -258,3 +258,58 @@ DESK_CHECK_TMPDIR=/data/tmp pnpm --filter @braedonsaunders/appkit-desk exec tsx
|
|
|
258
258
|
```
|
|
259
259
|
|
|
260
260
|
Set `DESK_CHECK_KERNEL_CMDLINE` for images that require a custom root device. The check creates and removes a disposable VM, overlay, snapshot, TAP and firewall rules. It verifies a guest HTTP stream before and after memory restore; it does not verify the proxy or cross-CPU migration. Choose addresses that do not overlap existing routes.
|
|
261
|
+
|
|
262
|
+
## macOS Virtualization.framework backend
|
|
263
|
+
|
|
264
|
+
On Apple silicon with macOS 14 or later, a host can supply a signed
|
|
265
|
+
`appkit-desk-vz` helper to `createVirtualizationBackend` and pass that backend
|
|
266
|
+
into `createDeskHost`:
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
import { createDeskHost, createVirtualizationBackend, isDeskSupported } from '@braedonsaunders/appkit-desk'
|
|
270
|
+
|
|
271
|
+
const helperPath = '/opt/appkit/bin/appkit-desk-vz'
|
|
272
|
+
if (!isDeskSupported({ helperPath })) throw new Error('This host cannot run desks.')
|
|
273
|
+
const backend = createVirtualizationBackend({ helperPath })
|
|
274
|
+
const host = createDeskHost({
|
|
275
|
+
imageRoot: '/var/lib/appkit/desk',
|
|
276
|
+
backend,
|
|
277
|
+
guestNetwork: { allowLan: false },
|
|
278
|
+
ports,
|
|
279
|
+
})
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The guest needs an arm64 Linux kernel, raw base image and the same desk guest
|
|
283
|
+
agent as the Linux backend. Use the kernel command line appropriate to the
|
|
284
|
+
image. Per-desk disks use macOS `cp -c`; provision the overlay directory on a
|
|
285
|
+
filesystem that supports cloning. The helper creates a userspace IPv4 network
|
|
286
|
+
with DHCP, defaults to `10.0.2.15/24` and gateway `10.0.2.2`, and blocks
|
|
287
|
+
private, link-local, shared and host addresses by default. RFC 5737 documentation
|
|
288
|
+
subnets (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`) are always blocked,
|
|
289
|
+
including when LAN access is allowed. Set `allowLan` only
|
|
290
|
+
when the host policy explicitly permits local network access. `DeskHandle.connect`
|
|
291
|
+
uses the helper's TCP relay; no routable guest IP on the Mac is required.
|
|
292
|
+
|
|
293
|
+
The npm package includes the Swift source under `vz/`. Build it on macOS with
|
|
294
|
+
Xcode and `vz/build.sh`; the script signs with the required virtualization
|
|
295
|
+
entitlement. Its default ad hoc signature is for local use. Distributors must
|
|
296
|
+
sign with their own Developer ID (`APPKIT_CODESIGN_IDENTITY`) and handle
|
|
297
|
+
notarization and distribution. The caller supplies the absolute installed
|
|
298
|
+
helper path; installation does not download or execute a binary. Save and
|
|
299
|
+
restore use a stable desk MAC and machine identifier; the host removes the
|
|
300
|
+
snapshot while the restored VM is paused before resuming it. The userspace
|
|
301
|
+
network is recreated on restore, so existing TCP and UDP flows must reconnect.
|
|
302
|
+
|
|
303
|
+
For a disposable macOS integration check, supply a prepared guest image with
|
|
304
|
+
its desk agent and Python 3, its matching `vmlinux` and `initrd`, and the signed
|
|
305
|
+
helper. In a source checkout, run `packages/desk/scripts/check-vz.mts` with `DESK_CHECK_IMAGE_ROOT`,
|
|
306
|
+
`DESK_CHECK_BASE_IMAGE`, and `DESK_CHECK_VZ_HELPER`; set
|
|
307
|
+
`DESK_CHECK_KERNEL_CMDLINE` if the image uses a different root device. The
|
|
308
|
+
check creates a temporary guest and tests guest execution, a private-host
|
|
309
|
+
network fence, guest TCP access, and memory save/restore. It removes the guest
|
|
310
|
+
and its temporary files on exit.
|
|
311
|
+
|
|
312
|
+
For clients that require a local TCP URL, `await listenDeskPort(desk, port)`
|
|
313
|
+
returns a loopback-only `{ host, port, close }` listener. Each incoming
|
|
314
|
+
connection opens a guest stream through `desk.connect`; call `close()` when the
|
|
315
|
+
lease ends to close the listener and its connections.
|
package/backend.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The backend port
|
|
2
|
+
* The backend port.
|
|
3
3
|
*
|
|
4
4
|
* `DeskBackend` is the seam that keeps the package testable without a
|
|
5
5
|
* hypervisor: the host asks a backend to boot a `DeskLaunchPlan` and gets a
|
|
6
6
|
* `DeskMachine` — a request/response channel to the in-guest agent plus an
|
|
7
7
|
* event subscription. CI and non-KVM developer machines inject an in-memory
|
|
8
|
-
* fake; production uses `cloudHypervisorBackend
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* fake; production uses `cloudHypervisorBackend` on Linux or
|
|
9
|
+
* `createVirtualizationBackend` on an Apple silicon Mac, whose process glue is
|
|
10
|
+
* deliberately thin because everything that can be pure lives in the plan
|
|
11
|
+
* builder, the protocol module, and the shared guest channel.
|
|
11
12
|
*/
|
|
12
|
-
import {
|
|
13
|
+
import type { ChildProcess } from 'node:child_process';
|
|
13
14
|
import type { Duplex } from 'node:stream';
|
|
14
|
-
import { DeskError, type DeskLaunchPlan, type DeskLauncherIdentity } from './plan.js';
|
|
15
|
-
import {
|
|
15
|
+
import { DeskError, type DeskHypervisor, type DeskLaunchPlan, type DeskLauncherIdentity } from './plan.js';
|
|
16
|
+
import type { GuestCommand, GuestEventMessage } from './protocol.js';
|
|
16
17
|
/**
|
|
17
18
|
* A request that was in flight when the guest connection dropped.
|
|
18
19
|
*
|
|
@@ -88,6 +89,16 @@ export interface DeskMachine {
|
|
|
88
89
|
* misbehaves for reasons nobody can find.
|
|
89
90
|
*/
|
|
90
91
|
onConnectionChange?(listener: (change: DeskConnectionChange) => void): () => void;
|
|
92
|
+
/**
|
|
93
|
+
* Open a TCP stream from the host to `port` on the guest.
|
|
94
|
+
*
|
|
95
|
+
* Optional: a backend whose guest has a routable address (Cloud Hypervisor's
|
|
96
|
+
* TAP) leaves this out and the host dials the guest address directly. A
|
|
97
|
+
* backend whose guest sits behind a userspace NAT (Virtualization.framework)
|
|
98
|
+
* provides it, because there is no address on the Mac to dial. Rejects with
|
|
99
|
+
* `DeskError` when the guest refuses or does not answer.
|
|
100
|
+
*/
|
|
101
|
+
connect?(port: number): Promise<Duplex>;
|
|
91
102
|
/** Stop the VM. Idempotent; resolves once the VMM process has exited. */
|
|
92
103
|
shutdown(): Promise<void>;
|
|
93
104
|
/**
|
|
@@ -123,6 +134,16 @@ export interface DeskBootHooks {
|
|
|
123
134
|
onRestored?: () => Promise<void>;
|
|
124
135
|
}
|
|
125
136
|
export interface DeskBackend {
|
|
137
|
+
/**
|
|
138
|
+
* Which hypervisor this backend boots, and so which plan the host builds
|
|
139
|
+
* for it. Absent means Cloud Hypervisor.
|
|
140
|
+
*/
|
|
141
|
+
readonly hypervisor?: DeskHypervisor;
|
|
142
|
+
/**
|
|
143
|
+
* The binary the backend launches — the VMM or the helper — for readiness
|
|
144
|
+
* reporting. Optional; `verifyDeskHost` falls back to its own option.
|
|
145
|
+
*/
|
|
146
|
+
readonly vmmPath?: string;
|
|
126
147
|
boot(plan: DeskLaunchPlan, hooks?: DeskBootHooks): Promise<DeskMachine>;
|
|
127
148
|
}
|
|
128
149
|
export type DeskProcessLauncher = (command: string, args: readonly string[], options: {
|
package/backend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
|