← KADAI Deutsch
KADAI · technical overview · as of September 7, 2026

KADAI under the hood

The core idea: A desktop that emerges from a description - not installed, but instantiated. Its foundation is a personal kernel: a small, encrypted, versioned self-description that can be instantiated and carried on anywhere - on any computer, in any VM, in the browser if need be. Every instance compiles the same desktop from it, compile(me.md, environment) → desktop, and whatever it learns flows back into the kernel: a system that follows the person, not the machine.

This page explains how: the data model, the key architecture, the four protocols, control through git as the control plane - and the threat model with its current gaps. Everything described here is running unless explicitly marked as design (validated August 2026, Plasma 6.6 / Ubuntu 26.04).

1 · Data model: the kernel

A Markdown file (me.md) with YAML frontmatter. Six sections with an explicit trust gradient: identity and facts (binding) · values (binding; decides trade-offs where no rule applies) · preferences (soft) · rules (inviolable without explicit consent - per action for anything that leaves the machine or cannot be undone) · episodic (current, possibly stale). Every entry carries a stable ID ({#r-001}) and a provenance line - when, by whom (human, model, machine). The frontmatter reserves a DID (did:kadai:…, so far without an external registry). Sections are meant to be addressable as MCP resources (me://rules …) - the single chokepoint where rules are enforced and access is logged.

The invariant: The kernel stores meaning, never configuration. “Focused in the morning, minimal distraction” - not “panel at the bottom, widget X”. Platform backends translate; that is why the same kernel is usable on Plasma, in a VM, or in a chat client.

Instruction and data (7 September 2026): The kernel is what the person said. The minimal instruction set is the founding page’s - six statements, three detected values, the rest derived. Observed data (devices, accounts, current working context) is not instruction: it can be collected again, lives in a store of its own (machine-local or held by the engine) and is referenced via me://. Valid means schema-conformant and encrypted to the register; current means last-updated per section plus regenerable data. Open: whether facts then still counts as “binding”.

2 · Key architecture

MaterialTypeCreatedLivesPurpose
Master identityage X25519once, at founding (browser or trusted machine)only passphrase-encrypted (scrypt) as master-key.age in the repo; plaintext never persistedroot of authorization: decrypts the kernel, admits new devices
Passphrasehuman secretchosen at foundingexclusively in your head; fed straight into scrypt when enteredguardian of the master identity - deliberately replaceable (later FIDO2/biometrics)
Machine identityage, per device: Secure Enclave (Mac), TPM 2.0 (Linux), otherwise an X25519 fileat join, in the device's security chip where it has oneprivate: in the chip, not readable; without a chip as a file (~/.config/kadai/age.key, 0600), and the device says so; public: in the registereveryday decryption without a passphrase; on the Mac with Touch ID per opening
Sync keyssh, per device: in the TPM (ecdsa) or as an ed25519 fileat join, locallyprivate in the chip or on the device; public as a deploy key at the repo host, with write accesstransport authorization to the repo without presence, so the hourly push runs unattended - orthogonal to content encryption
KeyringKeePass database + age-sealed passwordon the first machine, from the seed left by foundingkeyring.kdbx in the repo; its password in keyring.pass.age, encrypted to the registerthe accesses the system itself needs (storage, provider tokens); every machine opens it through one script, never as a file
VaultKeePass databasecreated by the personvault.kdbx in the repo; password only in the person's headthe person's own passwords; no tool and no model opens it
Human Repo (git host, sees only ciphertext) Device n Passphrase in your head only master-key.age master identity, sealed with scrypt .kadai-recipients device register: 1 age pubkey per authorized machine + master me.md.age kernel, encrypted to all recipients scripts · spec · history mechanics travel along; git = audit log unlocks defines the recipient set age machine key private, never leaves the device · pubkey in register Deploy key (ssh) transport gate: clone / pull / push me.md (plaintext) local only, gitignored; decrypted at login age -d with machine key Gate 1 (ssh): may I fetch the repo? Gate 2 (age): can I read the content? - independent of each other
No IdP, no PKI, no central directory: identity is possession (repo access) + knowledge (passphrase) + a self-managed device register in your own repo. The repo host (since October 2026 an own Forgejo server) is pure ciphertext storage with a metadata view. Revoking a device = an entry in the revocation list + re-encrypt, the keyring's password included.

3 · The four protocols

Founding (once per person - in the browser, entirely client-side)

  1. A deterministic dialog asks for name, preferences, passphrase, repo target; language, OS and time zone are detected rather than asked; the time zone is shown once for confirmation.
  2. In the browser: generate the master identity (age-js) → master-key.age (scrypt via passphrase) → generate the kernel from a template (incl. default rules r-001…r-003) → encrypt to master → register with the master pubkey.
  3. Publication: GitLab API (token) or a copyable bundle script (armored age files as heredocs, git init && push) for any git host. Accesses typed here (storage, provider tokens) are encrypted to the master identity and travel as the seed of the keyring. Secrets are wiped from memory after use; none of it leaves the browser unencrypted.

Join / enrollment (once per device - self-authorization)

  1. Two forms: the seed image for an empty machine, or a package with an assistant for a running Ubuntu (start/). The package knows where the repo lives and carries the master identity as in the repo plus a token, encrypted to it, that may enter deploy keys.
  2. Passphrase entry → master identity is unlocked in RAM only. The device creates machine and sync keys in the security chip (otherwise as files) and enters its sync key as a deploy key itself, through the token. Without a token it shows the key to enter by hand - the one human trust step.
  3. git clone → kernel decrypted with the master identity → device appends its pubkey to the register → re-encrypts kernel and keyring password to the extended recipient set → commits + pushes (“enroll”) → check: opens the kernel with its own key.
  4. From now on, everyday operation without a passphrase; plaintext master, token and passphrase are discarded. Proven on 2 October 2026 on an old notebook, from the address in the browser to the desktop.

Every boot (steady state)

  1. A systemd user instance starts at boot (linger): git pull as a merge, never a rebase → age -d with the machine key → me.md; the ordering Before=plasma-workspace.target guarantees: kernel before shell. Then a push, so this machine's state goes out.
  2. The graphical session starts (in the seed: autologin + immediate lock); the greeting reports the name + kernel commit time and, if any are waiting, proposals from a merge or a vault not yet merged.
  3. Reconciler: reads the shell's actual state (DBus), diffs it against desktop-spec.json from the repo, applies only the difference. Idempotent - second run: zero operations.

Sync (continuous)

  1. Every 10 min: a local commit, without network and without a key. A SHA-256 guard over me.md - only on a real change is it re-encrypted (age is not deterministic; without the guard there would be phantom commits). Changed mechanics, keyring and vault are committed along.
  2. Push at login, logout and hourly, over the sync key without presence. If it is rejected because another machine got there first: merge, then one more try. One merge driver per file (kernel per entry, register as a union, keyring per entry through KeePassXC, vault: own version stays, the other is kept next to it). The git history doubles as the audit log (which device knew what, and when).

4 · Control: git as the control plane

There is no control port and no remote-control session. Whoever wants to change the system - human or agent, from any device - changes declarations in the repo: the kernel (meaning) or the desktop spec (derived target state). Every machine reconciles itself at its next pull. Inbound connectivity is strictly a debugging tool. This is the same move as GitOps, except that the “infrastructure” here is a person together with their working environment - and the diff-and-apply step remains necessary because Plasma's own layout load is additive (a validated finding, not an assumption).

5 · Suggestions: a role, not a fixed model; rules as policy

Whatever makes suggestions is a role, and since 24 September 2026 the direction is reversed: subsidiarity. Two ladders, capability and place (0 without a model, 1 on this device, 2 on your network, 3 with a provider). The router starts at the smallest rung that has been sufficient for this class of task so far, checks the result with deterministic criteria and ascends one rung only on measured failure, at most twice. What the person accepts or discards lands in an append-only log per machine and sets the starting rung (stay from four in five acceptances, skip below a third). The deterministic floor remains: all mechanics (sync, join, reconciler, storage, keyring) are script-based and run without any model. Before rung 3 the router shows what would leave the machine, in bytes and with the recipient, and waits for a yes per action; rules from the kernel and a ceiling in the model register bind every rung. In the lab: a 0.8-billion model on the device, a 2-billion model on the network, a provider behind consent; the entrance is KRunner, the output cards in a rail at the right screen edge, never a chat (kadai-subsidiarity.md, poc/rung/).

6 · Threat model - what holds, what doesn't (yet)

Attack / lossStatus
Repo host compromisedreads only ciphertext (kernel) + plaintext mechanics/spec + metadata (commit times, sizes, device names in comments). Can tamper with history - commits are not signed (gap, see below).
Device lost/stolenRevocation: strike the register line, re-encrypt, delete the deploy key at the host. But: old ciphertexts in the history remain readable for the old key (no re-keying of the past), and the plaintext kernel sits on the device - genuinely exposed without disk encryption.
Offline passphrase brute forcepossible for anyone with a copy of the repo; scrypt makes it expensive but does not replace a strong passphrase. The guardian is designed to be replaceable (FIDO2/biometrics instead of a passphrase - design).
Malicious kernel pushwhoever has write access + a register slot is an authorized machine - by design. The line of defense is the register + transport gate, not the content.
Gap: unsigned commitsenrollment and sync commits are not cryptographically bound to the device; device signatures (ssh signing with the deploy key) would be the natural next step.
Largely solved (26 September 2026): keys on diskmachine and sync keys live in the security chip where the device has one (Secure Enclave on the Mac with Touch ID, TPM 2.0 in the VM). A device without a usable chip gets file keys and says so at join. Seed still without LUKS; moving from file to chip without leaving and rejoining is missing.
Gap: the keyring is as safe as the weakest deviceevery machine in the register can open keyring.pass.age, including one with file keys. That is why the keyring holds only what the system itself needs, and the person's own passwords live in the vault that only the person opens. A machine that left has seen the system accesses: revoking it also means changing them at their services.
Gap: the join tokenthe package carries a token that may enter deploy keys, encrypted to the master identity. On GitLab.com such a token reaches across the account, on an own Forgejo across the repo's account. Narrower would be a separate account for the kernel alone or, as the next step, ssh certificates signed by the person identity: then there is no token at all.
Gap: no forward secrecystatic age recipients; a machine key compromised later opens every ciphertext ever sent to it. Mitigation today: rebuild the history on key loss.
Gap: early historythe lab system carries plaintext sample data in old commits; production systems start with a fresh history (the founding page already does this).
Solved (23 Sept 2026): concurrent changestwo active machines changing the same kernel: git cannot merge the ciphertext me.md.age, so it hands the file to a merge driver, .kadai-merge.py. That merges per entry: a change on one side wins, the same change on both is fine, different changes keep this machine's version and write a proposal with all three versions to ~/.config/kadai/proposals/. No timestamp decides, nothing is overwritten silently, the repository is never left mid-merge. The base is the local plaintext copy .me.md.base from the last sync; .kadai-recipients uses git's built-in union driver because the list is an OR. Still open: observed data as an append-only log per machine, union instead of merge; derived state (spec, Activities) is recomputed per machine, never merged.
Deliberate non-goals: no central recovery service (passphrase lost + no authorized device left = new master needed), no anonymity towards the repo host, no protection against a compromised running machine of your own - there the kernel sits in plaintext, necessarily.

7 · Status

Validated (as of 3 October 2026): founding in the browser · joining via seed image (VM) and via package with assistant (old notebook, 2 October) · three machines in the register, active at once, merge per entry · keys in Secure Enclave and TPM, separate sync key · encrypted sync (local every 10 min, push at login/logout and hourly) with audit history · keyring and vault as KeePass files in the repo · boot ordering kernel-before-shell · idempotent reconciler · storage tier (Nextcloud, logged/reversible) · seed images arm64 and x86_64 · subsidiary router with two local models and a provider behind consent, KRunner entrance, rail (lab machine) · repo on an own Forgejo. Design: MCP module runtime with manifest/sandbox · model and rail on every machine · person identity on a FIDO key, then the phone · commit signatures · VHDX pipeline · observed data as a synced layer · the vault on the phone · moving file → chip without rejoining.

KADAI is a project by Jan Mühlig (muehlig@relevantive.de). Further reading: kadai-architecture.md (layers, decisions, §12 seed & identity), kadai-seed.md (image build and ceremony), me.example.md (kernel format). Crypto: age (X25519, P-256 in the security chip, scrypt for the passphrase), ssh for transport (ecdsa in the TPM or ed25519), KeePass KDBX 4 for keyring and vault, git as versioned ciphertext storage.