Capabilities & consent
What an app may ask for, what it may not, and what the user sees at install.
Capabilities are one shared vocabulary for both runtimes. Most of them — timers, storage, media, app data, staying awake — a device app can request, and they show in the Device column below. A companion-only set sits above the device's frozen model: host actions that reach into your Mac, which a device guest can never hold. Either way the default is fail-secure — nothing is granted until you allow it.
Only the wired bits are worth asking for. A wired bit is one a runtime really gates on, so requesting it grants a real capability. A floor bit is granted to every app unconditionally — there is nothing to request. A reserved bit is a constant that nothing checks yet; ask for it and you get a bit that does nothing at runtime.
- Bits
- 21
- Wired
- 13
- Floor
- 3
- Reserved
- 5
| Bit | Constant | Wire name | Status | Requestable | Device | Companion |
|---|---|---|---|---|---|---|
| 0 | CAP_SURFACE | surface | Floor | No | No | No |
| 1 | CAP_NAV | nav | Floor | No | No | No |
| 2 | CAP_TIMER | timer | Wired | Yes | Yes | Yes |
| 3 | CAP_LOG | log | Floor | No | No | No |
| 4 | CAP_KV_READ | kv-read | Wired | Yes | Yes | Yes |
| 5 | CAP_KV_WRITE | kv-write | Wired | Yes | Yes | Yes |
| 6 | CAP_NET_READ | net-read | Wired | Yes | No | Yes |
| 7 | CAP_NET_WRITE | net-write | Reserved | No | No | No |
| 8 | CAP_MEDIA_READ | media-read | Wired | Yes | Yes | Yes |
| 9 | CAP_MEDIA_WRITE | media-write | Wired | Yes | Yes | Yes |
| 10 | CAP_INPUT_READ | input-read | Reserved | No | No | No |
| 11 | CAP_INPUT_WRITE | input-write | Reserved | No | No | No |
| 12 | CAP_PRESENTATION | presentation | Reserved | No | No | No |
| 13 | CAP_HOST_ACTION | host-action | Wired | Yes | No | Yes |
| 14 | CAP_DATA_READ | data-read | Wired | Yes | Yes | Yes |
| 15 | CAP_DATA_WRITE | data-write | Wired | Yes | Yes | Yes |
| 16 | CAP_KEEP_AWAKE | keep-awake | Wired | Yes | Yes | Yes |
| 17 | CAP_CHROME | chrome | Wired | Yes | Yes | Yes |
| 18 | CAP_BACKGROUND | background | Reserved | No | No | No |
| 19 | CAP_HOST_FS_READ | host-fs-read | Wired | Yes | No | Yes |
| 20 | CAP_HOST_FS_WRITE | host-fs-write | Wired | Yes | No | Yes |
A bit is wired only if a runtime really gates on it — the status is scanned out of the device and companion runtimes, not asserted. Reserved bits exist as constants and enforce nothing; requesting one grants nothing. Floor bits are granted unconditionally, so there is nothing to ask for.
Why the Status column can be trusted
The status is not hand-written. It is scanned out of the two WASM runtimes — the device's and the companion's — by looking for the actual sites that gate on each bit. A bit is wired only if such a site exists, and CI fails if the table drifts from the runtimes. So the column tells you what will really be enforced, not what someone intended.
What the user sees
Your app declares the bits it needs in its manifest. Nothing is silently granted from that declaration — the companion turns it into a plain-language consent prompt the moment someone installs the app.
The dialog is titled Install YourApp? and lists, in plain words, everything the app will be able to do. Each line is decoded from the signed manifest, so the user consents to exactly what the runtime will enforce — never a hand-written list. A capability like kv-write reads as Save data on the device; net-read reads as Read from the network; keep-awake reads as Keep the screen awake.
An app that requests nothing beyond the floor shows a single reassuring line — Show its screens — no special permissions beyond the basics. Consent is all-or-nothing: the user allows the whole set, or cancels. There are no per-capability toggles.
Provenance is part of the prompt
Above the permission list, the dialog states where the bundle came from and whether its signature holds. The signature is what makes the permission list trustworthy — a tampered bundle could otherwise lie about what it asks for.
| The bundle | What the dialog says | Install button |
|---|---|---|
| Signed by Zeph, signature verified | Signed by Zeph and verified. | Enabled |
| Unsigned developer build | Unsigned developer app — only install apps you trust. | Enabled |
| Signed, but the signature fails | This app's signature is invalid — it may have been tampered with. | Disabled |
An unsigned bundle installs behind the same consent gate, so you can sideload your own work in progress. A bundle whose signature does not verify does not install at all.
Some grants name their reach
Holding a bit is sometimes necessary but not enough. Two of them carry a per-app allowlist in the signed manifest, and the consent prompt names each entry so the user sees the real reach:
- Network (
net-read) — Access specific websites, listing the exact hosts, or Access any website with an explicit warning when the app asks for every host. A device app can request it; the fetch is proxied through the companion. - Host actions (
host-action) — one line per privileged action: Run AppleScript on your Mac, Run shell commands on your Mac, each spelling out what it lets the app do. This one is companion-only — a device guest can never hold it, so it appears only for a hosted app's companion half.
Where the bits come from
The requires field in an app's manifest is the bitset behind all of this. See
The manifest for what rides the signed transfer
metadata, and Publishing for how a bundle gets signed
in the first place.