feat(apps): permission manager equips apps (manifest+consent+decisions in /system), launches via init w/ file grant; shell unprivileged (/home); install/apps/allow/revoke; revoke stops running app; app-image tool; counter app

This commit is contained in:
2026-10-27 22:56:44 +01:00
parent 9bc31a9bbe
commit 90e11eb2e8
51 changed files with 1766 additions and 644 deletions

View File

@@ -122,24 +122,26 @@ kept for the next one, except Ctrl+C, which signals the notification its
first `ON_INTERRUPT` caller gave. `REDRAW` repaints the screen and takes
input focus back.
The desktop is the shell, given the terminal, storage, the display and a
spawn allowance. Programs live in `/bin`, without extensions. A command
that is not a built-in runs `/bin/name`: the shell spawns it, gives it a
call-only copy of the terminal (as its log, so its output) and a read-only
storage grant to the shell's current directory (`cd`, `pwd`), writes its
arguments page, starts it, waits for its death (Ctrl+C kills it) and
releases the grant. `/bin/name.manifest` (`types::manifest`) asks for more:
`needs = display` gets the display (`StartArg::display`), with which the
program takes focus; the shell has the terminal redraw once it is gone. A
need the shell does not know, it refuses to run.
The desktop is the shell, given the terminal, the permission manager and
`/home` (its `/`). Everything the owner runs is an app (docs/apps.md): a
command that is not a built-in asks the permission manager (`types::apps`,
client `libkos::apps`) to run it, passing the terminal as its output and a
read-only grant to the current folder (`cd`, `pwd`). The permission manager
adds what the app's manifest asks for and the owner allowed (the display,
its own data folder), runs it, and hands back the process; the shell waits
for its death (Ctrl+C kills it), releases the grant, and has the terminal
redraw if the app had the display. `install`, `apps`, `allow` and `revoke`
manage apps.
Only init holds `ProcessCreate`. Everyone else runs programs through init's
spawn service (`types::spawn`, client `libkos::spawn`), which init serves
once boot is done. A manifest entry with `spawns` gets a badged copy of
init's endpoint, the badge naming its allowance. `SPAWN(name, limits)` loads
the program into a new, unstarted process, gives it a call-only log
endpoint, and replies with the process capability (Execute and Read, no
Delegate). The caller delegates whatever else the child should hold and
init's endpoint, the badge naming its allowance. `SPAWN(limits)` carries a
read-only storage grant to the program file itself; init loads it through
that grant (it needs no path, and loads nothing its requester could not
read) into a new, unstarted process, gives it a call-only log endpoint, and
replies with the process capability (Execute and Read, Delegate kept, so
the caller may pass it on to whoever it runs the program for). The caller delegates whatever else the child should hold and
starts it with `SpawnThreadIn`. The child's limits come out of the caller's
allowance (`OVER_ALLOWANCE` if they do not fit) and go back when init hears
the child die (`WatchDeath`, up to four watchers per process, so the caller