aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/superpowers/specs/2026-10-16-user-details-design.md97
1 files changed, 97 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-10-16-user-details-design.md b/docs/superpowers/specs/2026-10-16-user-details-design.md
new file mode 100644
index 0000000..2b2819b
--- /dev/null
+++ b/docs/superpowers/specs/2026-10-16-user-details-design.md
@@ -0,0 +1,97 @@
+# User details in the drawer
+
+## Goal
+
+Edit the user's own details from the drawer and write them where other
+applications already look for them, so LibreOffice, KDE apps, SDDM and git
+pick them up without being told.
+
+## Where the details live
+
+Measured on this machine:
+
+- **AccountsService** (`org.freedesktop.Accounts`, D-Bus activated, not a
+ running daemon until called): `RealName`, `Email`, `IconFile`, `Language`,
+ `Location`. Read by KDE's Users settings, GNOME and SDDM. `SetRealName`
+ also rewrites the GECOS field of `/etc/passwd`.
+- **GECOS** is what LibreOffice's `libdesktopbe1lo.so` reads to prefill its
+ user data (`givenname`). Name only, never email.
+- **`~/.config/emaildefaults`** (KEMailSettings, `[PROFILE_Default]`):
+ `FullName`, `EmailAddress`. Read by KDE mail apps.
+- **git** global config (`~/.gitconfig`): `user.name`, `user.email`.
+
+Polkit's `org.freedesktop.accounts.change-own-user-data` is implicit `yes` for
+any, inactive and active sessions, so no write prompts for a password.
+
+## Drawer row
+
+A row at the top of the drawer's grid view, above the notification list:
+the avatar in a circle, `Hello <login>` (the login name, `$USER`, which is
+fixed and not editable), and the real name as a smaller sub-line under it.
+Clicking it opens the user page; Escape and the mouse back button step out
+as on every page.
+
+## Module: `desktop/modules/user/`
+
+- `UserModule.qml`: name `user`, label `User`, a `page`. It sets
+ `tiled: false`, a new `Module` property (default `true`) that the drawer's
+ tile grid filters on, so the module has a page and no tile.
+- `UserRow.qml`: the drawer row. `Drawer.qml` places it above
+ `NotificationList` and calls `show("user")` on click.
+- `UserPage.qml`: the form. Avatar (click to choose a file with
+ `QtQuick.Dialogs.FileDialog`, as the KDE Connect module already does; shown
+ cropped to a circle, no cropping tool), name, email, language (a combo from
+ `locale -a`, UTF-8 entries only), location (free text), and a line previewing
+ what git will carry: `git: Jane D. <jane@example.org>`. A Save button sends
+ only the fields that changed.
+- `userctl`: bash, the only writer, like `statusctl`.
+
+The page reads values when it opens. The row reads them when the drawer
+opens.
+
+## `userctl`
+
+ userctl get # key=value lines: name, email, avatar, language, location
+ userctl set <key> <val> # writes one field everywhere it lives
+
+| Field | Writes |
+| --- | --- |
+| name | AccountsService `SetRealName`, emaildefaults `FullName`, git `user.name` (shortened) |
+| email | AccountsService `SetEmail`, emaildefaults `EmailAddress`, git `user.email` |
+| avatar | AccountsService `SetIconFile` (the daemon copies the file in) |
+| language | AccountsService `SetLanguage` |
+| location | AccountsService `SetLocation` |
+
+AccountsService is called with `busctl --system`, emaildefaults with
+`kwriteconfig6 --file emaildefaults --group PROFILE_Default`, git with
+`git config --global`.
+
+**Git name shortening.** The last whitespace-separated word becomes its first
+character and a dot: `Jane Doèr` becomes `Jane D.`. A single-word name
+is unchanged. The first character is taken by character, not byte, so an
+accented initial survives.
+
+`set` exits non-zero on the first failing write and prints the failing
+command's stderr. The page shows that text under the field, and leaves the
+field marked changed so Save retries it.
+
+## Extending
+
+A new detail is one entry in the field list in `UserPage.qml` and one `case`
+in `userctl`. No settings framework.
+
+## Testing
+
+`test-userctl.sh`: stub `busctl`, `kwriteconfig6` and `git` on `PATH` that log
+their arguments. Checks the shortening (two words, three words, one word,
+accented initial), that each field reaches exactly its stores, and that a
+failing stub makes `set` exit non-zero. It never calls the real
+AccountsService or touches the real git config.
+
+## Ceilings
+
+- Values are read on open; a change made elsewhere while the page is open is
+ not seen until it reopens.
+- No `~/.face.icon`: SDDM reads the AccountsService icon.
+- No vCard, no social links, no GPG key: nothing on the desktop reads them.
+ The field list is where they would go.