Skip to content

feat(s100): the desktop shell, proven on Linux - #118

Merged
HackTuah merged 2 commits into
mainfrom
slice/100-desktop-shell
Oct 8, 2026
Merged

HackTuah merged 2 commits into
mainfrom
slice/100-desktop-shell

Conversation

@HackTuah

@HackTuah HackTuah commented Oct 8, 2026

Copy link
Copy Markdown
Member

Slice 100, the desktop shell: everything that can be built and proven on Linux. The slice stays in_progress. macOS and Windows, and a real tray panel and notification daemon, are in its manual queue.

What lands

  • Trinity.Desktop: a behaviour with Tauri and Noop implementations. Noop is selected with no shell or when headless. Trinity.Desktop.Shell keeps the tray current and notifies on approvals, finished tasks and gateway messages while the window is not focused. Notifications carry names only, never arguments.
  • Secrets: the OS keychain first and the environment second (Trinity.Secrets). The shell binary runs as a helper; values travel hex-encoded over stdin and stdout, never on a command line. With no keychain, storing is an error, never a file.
  • Receipt signing key: it moves into the keychain by rotation when one answers. The old key is retired with valid_until, and a move interrupted by a crash resumes. Headless and regulated builds are unchanged and stay file-backed.
  • Shutdown: quitting mid-turn keeps what arrived. prep_stop interrupts every session before the Repo stops.
  • Settings and first-run setup: /setup and the Settings page. Folders chosen there extend the file tool's roots, and only those two screens write them.
  • Tauri shell: single instance, a global shortcut, autostart, a native dialog, clickable notifications, and a SIGTERM to the sidecar's BEAM. The sidecar is started with --no-halt, which was the packaged-app red. 54 crates are added and none changed; tauri stays at 2.11.5.
  • package.yml: checks three new smoke lines (FTS5, WATCHER, MODEL_CACHE) on all three OSes.

Criteria

  • AC6 (key migration): proven.
  • AC10 (boots with or without a shell): proven, as spawned OS processes.
  • AC9 (packaged smoke): proven on linux x86_64. macOS and Windows wait on this branch's package run.
  • AC1 to AC5, AC7, AC8: proven on Linux under an isolated Xvfb, a private D-Bus and a throwaway gnome-keyring. Fakes stand in for the notification daemon and the tray host.
  • macOS and Windows: queued, with exact steps.
  • AC11: partly. The flow is tested, and the packaged app opens on /setup. A first turn with a real key is the owner's.

Evidence

  • Author's gate: exit 0, 1033 passed (20 properties, 1013 tests), 18 excluded, prod_check: PASS, coverage 80.37% against 80.31%.
  • Reviewer re-run before commit: the 13 changed and new test files, 85 passed. mix format --check-formatted OK; mix credo --strict --all found no issues.

Before slice 101

The bundle identifier is still the generator's you.app.trinity. Single instance, notification identity and autostart all derive from it, so it needs a real value before signing.

Slice 100, everything that can be built and proven on Linux. macOS and
Windows, and a real tray panel and notification daemon, are in the
slice's manual queue.

- Trinity.Desktop is a behaviour with Tauri and Noop implementations. Noop
  is selected with no shell or when headless.
- Trinity.Desktop.Shell keeps the tray current and notifies on approvals,
  finished tasks and gateway messages when the window is not focused.
  Notifications carry names only, never arguments. Only a hello carrying
  the launch token is trusted.
- Secrets come from the OS keychain first and the environment second,
  through the shell binary run as a helper. Values travel hex-encoded on
  stdin and stdout, never on a command line. With no keychain, storing is
  an error, never a file.
- The receipt signing key moves into the keychain by rotation when one
  answers. The old key is retired with valid_until, and a move interrupted
  by a crash resumes. Headless and regulated builds stay file-backed.
- Quitting during a turn keeps what arrived: prep_stop interrupts every
  session before the Repo stops, and Session.terminate/3 is the backstop.
- Settings and a first-run setup flow. Folders the owner chooses there
  extend the file tool's roots; only those two screens write them.
- The Tauri shell gains single instance, a global shortcut, autostart, a
  native dialog, clickable notifications, and a SIGTERM to the sidecar's
  BEAM. The sidecar is started with --no-halt.

The red evidence is in the slice NOTES: 57 of 74 tests failing at their own
assertions, and the packaged sidecar halting a second after boot.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
…n is SQLite only

Run 37743757349 failed on all three OSes because a fresh bundle answers `/` with 302 to
`/setup` (AC11), which is intended. The step now follows the redirect and fails unless it
lands on `/` or `/setup` with a 200.

Run 37743785739 (postgres) failed AC5's `assert files != []`: that job has no database
file to read. The `strings trinity.db` scan is now its own test tagged :sqlite, and the
keychain, render and log assertions still run on both adapters.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
@HackTuah
HackTuah merged commit 2a7b8b7 into main Oct 8, 2026
16 checks passed
@HackTuah
HackTuah deleted the slice/100-desktop-shell branch October 8, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant