150 lines
5.7 KiB
Markdown
150 lines
5.7 KiB
Markdown
# Apps, manifests and the permission manager
|
|
|
|
How a program gets its authority. The kernel only knows capabilities; this
|
|
is the userspace layer that decides who holds which, on the owner's behalf
|
|
(see the vision's Capability Management and App Manifest notes).
|
|
|
|
## Apps
|
|
|
|
Every program the owner runs is an **app**: a manifest plus a binary.
|
|
An app is identified by its **id** (`kos.snake`), never by a file name or a
|
|
process id. The id is what decisions, the app's data folder and (later) its
|
|
encryption keys hang off.
|
|
|
|
System servers (log, display, terminal, storage, …) are not apps: init
|
|
starts them from its own table, with exactly the capabilities listed there.
|
|
|
|
## Where authority comes from
|
|
|
|
An app's capabilities have exactly two sources:
|
|
|
|
1. **Its manifest and the owner's consent.** Services the app declared
|
|
(`display`, `storage`, …), granted only by the permission manager, only
|
|
as far as the owner approved.
|
|
2. **Its launcher.** Whoever starts an app may pass along what it already
|
|
holds: the terminal as its output, a read-only grant to the current
|
|
folder, a file the owner picked. A launcher can only give what it has.
|
|
|
|
`cat` declares nothing and gets only what the shell passes it. Snake
|
|
declares `display`. Nothing gets anything "just in case".
|
|
|
|
## Disk layout
|
|
|
|
```
|
|
/home/ the owner's files; the shell's `/`
|
|
/apps/<id>/ an installed app: manifest.toml and its binary
|
|
/data/<id>/ the app's private folder (its `storage` capability)
|
|
/system/permissions/ the owner's decisions, one file per app id
|
|
/bin/ system servers and the shell (init starts these)
|
|
```
|
|
|
|
Only the permission manager reaches `/apps`, `/data` and `/system`. The
|
|
shell's storage grant is `/home`, so neither it nor anything it runs can
|
|
read another app's data or rewrite a decision.
|
|
|
|
## Manifest
|
|
|
|
`/apps/<id>/manifest.toml`, a strict subset of TOML:
|
|
|
|
```toml
|
|
[app]
|
|
id = "kos.snake" # required: lowercase reverse-DNS
|
|
name = "Snake" # required
|
|
version = "1.0.0" # required: major.minor.patch
|
|
binary = "snake" # required: a file in the app's folder
|
|
command = "snake" # optional: what the shell runs it as (default: binary)
|
|
author = "K-OS" # optional
|
|
icon = "icon.png" # optional: a file in the app's folder
|
|
|
|
[capabilities]
|
|
required = ["display"] # cannot work without; denied = not installed
|
|
optional = [] # works without; the owner decides each
|
|
|
|
[appearance]
|
|
accent = "#e91e63" # optional: checked for format here, contrast by K-UI
|
|
```
|
|
|
|
The subset: `[table]` headers, `key = "string"`, `key = ["a", "b"]` on one
|
|
line, `#` comments. Strings hold printable ASCII without `"` or `\`. It is
|
|
strict: an unknown table, key or capability name, a duplicate, or a
|
|
missing required key rejects the manifest. Nothing is ignored silently.
|
|
|
|
Capability names come from the server catalog (`display`, `storage`,
|
|
`network`, `telephony`, …). A name is valid even if this device lacks the
|
|
server; a required one it lacks means the app cannot be installed here, an
|
|
optional one is simply not granted.
|
|
|
|
| Capability | What the app gets |
|
|
|---|---|
|
|
| `display` | the display server: the screen, and the keyboard while in focus |
|
|
| `storage` | `/data/<id>/`, read-write (its own folder only) |
|
|
|
|
## Decisions
|
|
|
|
`/system/permissions/<id>`, the same TOML subset:
|
|
|
|
```toml
|
|
[decision]
|
|
granted = ["display"]
|
|
```
|
|
|
|
Written by the permission manager when the owner decides; apps on the
|
|
system image ship with their decisions already recorded (pre-approved by
|
|
whoever built the image). Changing one later is the owner's call, through
|
|
the permission manager.
|
|
|
|
## Permission manager
|
|
|
|
A system server with no hardware. Its logic (checking manifests, deciding
|
|
what an app gets, keeping decisions) is pure and generic over two ports:
|
|
|
|
- `Consent`: asks the owner. Today: a yes/no prompt on the terminal.
|
|
- `Store`: reads manifests and decisions, writes decisions, installs files.
|
|
Today: the storage server.
|
|
|
|
Both have mocks; the logic is tested on the host with `cargo test`.
|
|
|
|
### Install
|
|
|
|
From a folder the launcher passes as a read-only grant:
|
|
|
|
1. Read and check its `manifest.toml`; refuse if the id is installed.
|
|
2. Required capabilities this device lacks: refuse.
|
|
3. Ask the owner about the required ones together (no = not installed),
|
|
then each optional one.
|
|
4. Copy the binary and manifest to `/apps/<id>/`, create `/data/<id>/` if
|
|
`storage` was granted, record the decision.
|
|
|
|
### Launch
|
|
|
|
The launcher names an app (by command or id), passes its arguments and the
|
|
capabilities it wants to pass along (output, current folder). The
|
|
permission manager:
|
|
|
|
1. Looks the app up and reads its decision.
|
|
2. Gives init a read-only grant to the binary; init loads it from that
|
|
grant into a new, unstarted process (init needs no path, and nothing is
|
|
spawned that its requester could not read).
|
|
3. Gives the process the granted services and what the launcher passed,
|
|
writes its arguments page, starts it.
|
|
4. Watches it die, then releases its storage grants.
|
|
5. Replies with a handle (the process capability, call-only) the launcher
|
|
can wait on and kill.
|
|
|
|
### Revoke
|
|
|
|
The owner withdraws a capability: the decision changes and the next launch
|
|
gets less. A running app that held it is **stopped**: all its access dies
|
|
at once. (Endpoint capabilities like `display` are copies the permission
|
|
manager cannot take back from one app alone yet; once servers issue
|
|
per-client badges, as storage does, revoking a single capability from a
|
|
running app will not need to stop it.)
|
|
|
|
### Not yet
|
|
|
|
- A trusted path for the consent prompt: today an app could draw a fake
|
|
prompt on the terminal (it cannot answer one; apps cannot type).
|
|
- Suspicious-combination warnings, simple/granular consent, per-host or
|
|
other server-side scopes.
|
|
- Signing, updates, uninstall.
|