{"path":"research/deliberus-as-a-desktop-app.md","content":"# Deliberus as a desktop app: what it would take\n\n**Date:** 2026-10-11\n**Standing:** an investigation the founder asked for. Nothing here is built, nothing is ruled, and\nevery size is an estimate that no run has measured.\n\n---\n\n## 0. His words\n\nOn what draws the graph in Lins, his graph explorer, after a trial showed the same scene drawn by\nthe browser and by a Rust renderer (the trial is recorded in `graph-visualization.md`):\n\n> \"So, browser-drawn it is. Just like the Fyr way of doing it.\"\n\nFyr is his assistant application: a small Rust program that owns the window, with the interface\ndrawn by the system's web view. And then:\n\n> \"This also means that Deliberus could be provided/released as a desktop app for those who would\n> prefer to use it that way, eventually. Investigate how much work that would be, if we learn from\n> how Fyr and Lins are built.\"\n\n*Eventually* is his word. This note sizes the work and proposes an order. It does not propose\ndoing it now: the four open reviews outrank it.\n\n---\n\n## 1. In short\n\n*A desktop app* can mean three different things, and the work differs by two orders of size.\n\n| | What it is | What a person gets | Work | Money |\n|---|---|---|---|---|\n| **1. Installed from the browser** | The site, saved as an app by the person's own browser | Its own window and an icon in the Dock or taskbar | About an hour, to make browsers offer it under the right name and icon. It already works without any change | None |\n| **2. A shell around the live site** (the way Fyr is built) | A small Rust program with a window that shows deliberus.com | The above, and what only a program can do: a key that captures a thought from anywhere, links that open in the app, later more | Days: about four to six, to a signed Mac app with sign-in | 99 US dollars a year to Apple; Windows signing on top, not priced here |\n| **3. Deliberus on your own machine** | The server, the graph and the database inside the app, on the person's computer | A private graph, and their own model access paying for the reading | Weeks, and most of it is deciding, not building | The same fees |\n\nThe first is nearly free and can be done whenever. The second is real work with one hard part,\nsigning in, and one part neither sibling project has ever done, releasing. The third is a\ndifferent product, and it meets a standing principle head on (§ 5).\n\n---\n\n## 2. What the two sibling projects teach\n\nBoth were read for this note.\n\n**Fyr** (Tauri 2, a Rust shell around a SvelteKit page):\n\n- The shell itself is small and proven: a window, two plugins (one remembers the window's place,\n  one opens links in the system's browser), and a settings file. Its page is built the same way\n  Deliberus's is (a static, client-rendered SvelteKit build).\n- It runs a second program beside itself and talks to it (a Node helper that drives a coding\n  agent). That is the pattern form 3 would need for Deliberus's Python server.\n- It can be driven and photographed by a test in its development builds: Apple ships no test\n  interface for the web view a Mac shell uses, so a plugin runs one inside the app.\n- Its Windows study found the shell solid there (the system's web view ships with Windows 11; one\n  of the two installer formats is broken when a helper program is bundled, the other works), and\n  found that **the embedded graph database it wanted does not run on Windows**. Its answer was to\n  keep the graph on a server and reach it over the network.\n- **What Fyr does not teach is release.** It has never been signed, notarised, given an update\n  channel, or handed to another person. Its own notes say no release build existed in March.\n\n**Lins** (a Rust server that carries its page inside one binary, opened in a browser):\n\n- *The server carries the page* is how Deliberus already works: the same process answers the\n  interface and serves the page.\n- Its trial of two renderers is the reason for this question, and it carries one caution for it:\n  the two halves looked identical in the one browser engine they were tried in. A Mac shell shows\n  pages with Safari's engine, and nothing of Deliberus's has been tried there by this\n  investigation.\n- Lins has no desktop shell yet. It is on its own roadmap. So a shell for Lins and a shell for\n  Deliberus are the same work twice unless one is built to be the other's template (§ 6).\n  *(Built 2026-10-12: § 8.)*\n\n---\n\n## 3. Form 1: installed from the browser\n\nA person can already do this with no change on our side. Safari on a Mac (macOS 14 and later)\nsaves any page as an app from its File menu, *Add to Dock*; Chrome and Edge install any site as\nan app from their menus. The result has its own window and icon. Signing in works as it does on\nthe web, because it is the person's own browser.\n\nWhat an hour buys: a small file that names the app and its icons (a web app manifest: a name, two\nicon sizes, a start address, a display mode) and two lines in the page's head. With it, Chrome and\nEdge offer the installation themselves and use our name and icon. They ask for nothing beyond\nthat file and a secure address.\n\nWhat it cannot do: anything outside its window. No key that works while another app is in front,\nno reading of a local model.\n\n---\n\n## 4. Form 2: a shell around the live site\n\n### 4.1 The window shows the live site, and this is where it differs from Fyr\n\nFyr carries its page inside the app, because its server part is inside the app too: page and\nserver change together, in one release. Deliberus's page and server also change together, on the\nserver, several times a week. A page carried inside a desktop app would fall out of step with the\nserver it talks to at the first deploy after a release. So the shell's window should show\n`deliberus.com` itself. The page is then always the current one, and the shell changes rarely.\n\nA consequence worth saying plainly: form 2 is a browser window with extras. What justifies it over\nform 1 is only the extras (§ 4.5).\n\nHad the page been carried inside the app, three things would need changing that the live-site\nchoice avoids: the page works out its server's address by one expression repeated in fifteen\nfiles, which gives the wrong answer inside a shell; the sign-in cookie is not sent across origins\nas it is set today; and the server's list of allowed origins would need the shell's own.\n\n### 4.2 Signing in is the one hard part\n\nGoogle refuses its sign-in page inside an app's web view. Its documentation names the web view\nthat a Mac shell uses, and requires an installed app to open the system's browser instead. So a\nperson cannot press *Sign in with Google* inside the shell and have it work.\n\nThe way through keeps Google out of the shell altogether:\n\n1. The app opens the person's own browser at a sign-in address on deliberus.com.\n2. They sign in there as on the web.\n3. The server hands the browser a one-time code and sends it back to the app (by a link the app\n   has registered, or to a listener the app opened on the machine itself).\n4. The app's window exchanges the code for a session, once.\n\nThe server already has a small relative of this: a short-lived signed link that carries a mark\nfrom one of the keeper's devices to another. That mark only quiets notifications. A code that\ncarries a whole session is a far more sensitive thing: it must work once, last a minute or two,\nand be tied to a secret the app made before step 1, so that a copied code is worth nothing. It\nwants a security read before it ships.\n\n### 4.2a What *the system's browser* means, and how other apps do it\n\n*Added 2026-10-11, on the founder's questions: \"What do you mean 'go through the system browser'?\nEmbed a Safari web-view inside a Rust-based Mac app?\" and \"How do apps like Discord or TickTick\nsolve this, aren't they using Google OAuth?\"*\n\n**It is the reverse of embedding.** A shell's own window *is* an embedded browser: a piece of\nSafari's engine that the app owns and draws into (a web view). That is exactly where Google\nrefuses to show its sign-in page. The reason is that an app can read and change whatever is shown\nor typed in its own web view, so a person typing a Google password there is typing it into the\napp. *The system's browser* is the person's ordinary browser, as its own program (Safari, Chrome,\nZen), which the app cannot see into.\n\n**Google blocks the page, not the app.** It has refused sign-in inside embedded web views since\n2017 (announced August 2016, for iOS, Android, Windows and the Mac), and inside Electron's\nembedded browser since January 2021 by a vendor's account. The error a Mac web view gets is\n`disallowed_useragent`. Apps built this way are common and they all sign people in; they do it\noutside their own window.\n\n**The round trip every such app makes:**\n\n1. The app opens the sign-in address in the person's browser.\n2. The person signs in there, where their Google session usually already exists.\n3. The browser hands the result back to the app, one of two ways: by a link the app has\n   registered with the system under its own name (the system starts or focuses the app and gives\n   it the link), or by calling a small listener the app opened on the machine itself for the\n   occasion.\n\nApple also offers a sign-in sheet for this (`ASWebAuthenticationSession`); on a Mac it opens the\ndefault browser, and Google's own sign-in kit for Apple platforms uses it.\n\n**Read from the apps on the keeper's machine** (each app's own declaration of the links it has\nregistered):\n\n- **TickTick** (not an Electron app; it has Google sign-in) registers a link under its own name and a\n  second one issued by Google for exactly this return trip. That second link is the mark of\n  Google's sign-in kit: browser out, link back.\n- **Discord** (an Electron app) registers a link under its own name. Its help pages list no\n  Google sign-in: e-mail or phone with a password, a code scanned from the phone, and passkeys.\n- **Claude's desktop app** (Electron) registers a link under its own name and a second one of the\n  kind a sign-in kit uses for the return trip.\n\n**For Deliberus the hard rule falls on the server, where it is already met.** Google's page is\nopened by deliberus.com and returns to deliberus.com, as on the web, so nothing about Google's\narrangement changes. The app never talks to Google. What travels back to the app is our own\none-time code (§ 4.2), which is why its design matters and Google's rules for desktop clients do\nnot come into it.\n\n**In Tauri**, the pieces exist: the plugin that opens a link in the system's browser (Fyr uses\nit), an official plugin for registered links, and a small community plugin that opens the listener\non the machine (`tauri-plugin-oauth`, desktop only). By one developer's write-up a registered\nlink is the fragile one on Windows, where it works only from an installed build; the listener\nworks in development too. Not tried here.\n\n### 4.2b The same problem in Fyr, in another shape\n\nThe founder: *\"This is a problem I'd guess we need to solve for both Deliberus and Fyr.\"* Read in\nFyr's code and notes, the two share the release work for certain, and the browser round trip, and\ndiffer in what is signed in to.\n\n- **Deliberus** signs a person in to *our* server. Google is behind the server. The app needs our\n  session handed over from the browser.\n- **Fyr has no account of its own.** Each person signs in to their model subscription through its\n  command-line tool, which opens the browser itself. What Fyr needs is to *connect outside\n  accounts*: a task service today, by a token read from a file with the sign-in step left for\n  later, a calendar in its plans, and *per-connector sign-in* listed among its open design items.\n  There the app itself is the client: browser out, listener on the machine back, and the tokens\n  belong in the system's keychain.\n\nSo a shell built first for one gives the other its window, its release steps and its round trip,\nand not its sign-in design.\n\n### 4.3 Release, which is new ground\n\n- **A Mac app that others can open** must be signed with a certificate from Apple's paid\n  developer programme (99 US dollars a year) and passed through Apple's notarising service.\n  Without that, a downloaded app is reported as unverified or broken.\n- **One membership covers every Apple platform**: iPhone, iPad, Mac, Watch, TV and Vision. So the\n  same fee would release a Mac app and an iPhone app, of any of his projects. Apple states the\n  price as 99 US dollars a membership year, shown in local currency at enrolment (the figure in\n  kronor was not seen). An individual enrols under their legal name, which is shown as the\n  seller. The fee is waived only for nonprofits, schools and government bodies.\n- **What needs no membership**: building an app and running it on his own Mac, and installing\n  his own build on his own iPhone, where it stops working after seven days and has to be built\n  again (three devices at most). The fee buys handing an app to someone else.\n- **Updates**: the shell's own updater needs a signing key of ours and somewhere to publish each\n  release. With the page live from the server, the shell would update seldom.\n- **Windows**: a second build and a second signing arrangement, not priced here. Fyr's study says\n  the shell itself is solid there.\n- **Linux**: a third build, on a third web engine.\n\n### 4.4 Safari's engine\n\nThe site is developed and checked in Chrome's engine. A Mac shell shows it with Safari's. The\nmaps, the voice input and the text clamping are the places to look first. This may turn up\nnothing; it has not been looked at.\n\n### 4.5 What would make it worth having\n\n- **A key that captures a thought from anywhere**, by typing or by voice, into the person's own\n  drafts. The product's north-star interaction is voice-first, and *capture immediately, publish\n  deliberately* is a standing principle; a web page cannot hear a key pressed in another app.\n- **Links that open in the app**: a claim's address opening the app at that claim.\n- **Later**: reading a model that runs on the person's machine, which is the first step toward\n  form 3.\n\n### 4.6 Size\n\n| Piece | Estimate |\n|---|---|\n| The shell: window on the live site, window memory, outside links to the system's browser, one running copy, app links, a menu | Half a day, most of it taken from Fyr's setup |\n| Sign-in through the system's browser: server side, app side, tests, a security read | A day |\n| First release on a Mac: enrolment with Apple, certificate, notarising, an update channel | One to two days of work, and a wait on Apple that is not ours to shorten |\n| A check of the site in Safari's engine, and whatever it finds | Unknown; half a day if it finds little |\n| Each extra of § 4.5 | Half a day to a day |\n| Windows | A day or two more |\n\nThese are estimates by the session that wrote this, at the pace its own work has run at. None is\nmeasured.\n\n---\n\n## 5. Form 3: Deliberus on your own machine\n\nThe pieces, each read from the code:\n\n- **The server** is Python, and its installed packages, the development ones included, come to\n  about 285 MB. It would run beside the shell as a helper program, as Fyr's helper does.\n- **The graph** has an embedded form that the test suite already uses. Fyr's study found that\n  package does not run on Windows. The licence of the engine inside it was not checked.\n- **The database** layer is written for Postgres. One newer part of the code already runs on a\n  file-based database as well; the main part does not.\n- **The workflow service** is not needed: the server already falls back to running an extraction\n  in its own process when the service is absent.\n- **Embeddings** come today from a model on the production host. A local app needs its own source.\n- **Model access**: an engine that pays through a prepaid account exists, built for the keeper's\n  own account; the same route with a reader's own key is not built\n  (`whose-tokens-pay-for-mapping.md`). That note also found the one case where a person's\n  ChatGPT plan can pay for a tool today: an open-source tool that runs on their own machine,\n  which is this form.\n\nThe packaging is the smaller part. The larger part is a question about what Deliberus is: **a\ngraph on one person's machine is a separate universe unless it has a defined relation to the\ncommons**, and *one graph, staged maturity, never a separate draft universe* is a standing\nprinciple. The nearest thing built is the compartment a community can have, with its own written\nmembrane and its own store (`blobs-community-sandboxes-and-the-advice-process.md`). A personal\ncompartment that publishes into the commons deliberately would be the same idea at the size of\none person, and how its claims meet the commons' claims is the sameness question again. None of\nthat is designed.\n\nSo form 3 is not proposed here. It is recorded because it is where a desktop app stops being a\nconvenience and becomes a way for a reader's own model access to pay for mapping.\n\n---\n\n## 6. A proposed order (unruled)\n\n1. **Form 1 whenever it suits**: the manifest and icons. An hour, no fees, and it is the whole of\n   *for those who would prefer to use it that way* for most people who would.\n2. **The shell is built first for Lins** *(done 2026-10-12, § 8)*, which needs no sign-in and no fees while only its owner\n   uses it, and whose roadmap already holds it. What is learned there about the shell and about\n   release is then reused: Deliberus adds the sign-in of § 4.2 and little else.\n3. **Form 3 waits on a decision**, not on work: whether a private graph on a person's machine is\n   something Deliberus should be.\n\nNone of this is review work, and the reviews come first.\n\n---\n\n## 7. What was not checked\n\n- Deliberus's pages in Safari's engine.\n- Whether Google sign-in completes inside a Safari web app made with *Add to Dock*, or only\n  carries over a sign-in made in Safari first.\n- What signing a Windows build costs.\n- The Tauri plugins named in § 4.2a: read about, not run.\n- How TickTick's and Claude's apps make the round trip in full: only the links they registered\n  were read, not a sign-in watched.\n- Whether Google asks for a review of an app like Fyr before strangers may connect a Google\n  calendar or mailbox through it. It has such reviews for some kinds of access.\n- The licence of the graph engine inside the embedded package.\n- How Fyr takes sound from the microphone, which bears on voice capture in a shell.\n- Every size above.\n\n## 8. The shell for Lins, built (2026-10-12): what carries over\n\nHis word: *\"Fyr works, and I want Lins to be possible run as desktop, so let's just do it now right\naway.\"* Seventeen minutes later, on seeing it: *\"Looks marvelous, even has its own dock icon.\"* The\nsecond step of § 6 is done. The record of how it is made is in\n[graph-visualization.md](graph-visualization.md) § 11, its last subsection.\n\n**Its size.** One new program of 136 lines, the server's code moved so that the app can hold it,\na page of 38 lines for when the database does not answer, a build script, an icon. One line\nchanged in the page itself. Twenty-four files in all.\n\n**What a shell for Deliberus can take from it as it stands**\n\n- The layout of the program and its settings file for a Mac app with its own name, icon and\n  dock place.\n- A window opened on an address, and kept to that address: a link that leads elsewhere does not\n  load inside the window.\n- The window's place and size remembered between runs.\n- A page shown when the thing behind the window does not answer, with the reason, in place of a\n  blank window.\n- A script that builds the app and installs it outside the build folder.\n- *(2026-10-14)* An app opened from the dock that knows what to open: it keeps what a command last\n  started it with, the password in the system keychain and never in a file\n  (`lins-app/src/remembered.rs`). And a lesson about signing: a certificate made on the Mac keeps an\n  app's designated identity across builds, but macOS still ties a keychain item to each build's own\n  fingerprint when the app has no Apple team ID, so a rebuilt app is asked again (seen 2026-10-15).\n  A released app, with a Developer ID, would not be. Both apply to Fyr, which is signed ad hoc.\n\n**What it does not answer for Deliberus**\n\n- **Sign-in** (§ 4.2). Lins has none. This is still the hard part, untouched.\n- **Release** (§ 4.3). The app is signed for the machine it was built on and has been handed to\n  nobody. Signing for other people's machines, Apple's check, and updates are as new as before.\n- **Where the window's content comes from.** Lins's shell holds its own server and shows that. A\n  shell for Deliberus shows the live site (§ 4.1), so that half of the work is of no use to it.\n- **Safari's engine for Deliberus's own pages** (§ 4.4). Lins's page draws in it, graph included.\n  Deliberus's maps, voice input and text clamping have still not been looked at there.\n\n**One thing it showed that § 4.6 does not list.** A Mac app signed only for its own\nmachine is a new app to the system after every rebuild, and the system asks its permission\nquestions again. For Lins that is one question, about the local network. For a shell around a\npublic site it would not arise. It is a reason to sign properly early if the shell is ever\nrebuilt often.\n\n**On the sizes in § 4.6.** That table gives the shell half a day. The part of it built here (the\nwindow, its memory, the icon, the bundle, the install) took seventeen minutes from his word to\nhis seeing it. Links that open in the system's browser, a single running copy, links into the\napp and a menu were not built. Nothing here measures sign-in or release, which is where the\ntable puts most of its days. So the whole is neither confirmed nor reduced; only part of its\nsmallest row is now measured.\n\n## Sources\n\n- Google, *OAuth 2.0 for iOS & Desktop Apps*: installed apps open the system's browser; the\n  `disallowed_useragent` error for sign-in inside a web view.\n  https://developers.google.com/identity/protocols/oauth2/native-app\n- Google Developers Blog, *Modernizing OAuth interactions in Native Apps* (August 2016): sign-in\n  refused in embedded web views, on which platforms, from which dates, and why.\n  https://developers.googleblog.com/modernizing-oauth-interactions-in-native-apps-for-better-usability-and-security/\n- ToDesktop, *Google OAuth Screen*: a vendor's account that Google has refused sign-in inside\n  Electron since 4 January 2021, and the browser-then-link-back remedy.\n  https://www.todesktop.com/builder/docs/application/google-oauth-screen\n- Google's sign-in kit for Apple platforms, issue 388: its maintainers on the sign-in sheet\n  opening the default browser on a Mac, quoting Apple's documentation.\n  https://github.com/google/GoogleSignIn-iOS/issues/388\n- `tauri-plugin-oauth` (the listener on the machine). https://docs.rs/crate/tauri-plugin-oauth/latest\n- A developer's write-up of desktop sign-in in Tauri 2 (the Windows remark in § 4.2a).\n  https://github.com/Playmoir/knowledge-base/blob/main/tauri-desktop-oauth.md\n- Discord, *How to Log In to your Discord Account*.\n  https://support.discord.com/hc/en-us/articles/360057027354-How-to-Log-In-to-your-Discord-Account\n- Apple, *Membership Details*, *Become a member* and *Developer account overview*: what one\n  membership covers, the fee, and what is possible without it.\n  https://developer.apple.com/programs/whats-included/ ·\n  https://developer.apple.com/programs/enroll/ ·\n  https://developer.apple.com/support/compare-memberships/\n- Tauri 2, signing for macOS: the paid programme, the certificate for apps shipped outside the\n  store, notarising.\n  https://github.com/tauri-apps/tauri-docs/blob/v2/src/content/docs/distribute/Sign/macos.mdx\n- Tauri 2, updater, deep linking, and access for remote pages:\n  https://v2.tauri.app/plugin/updater/ · https://v2.tauri.app/plugin/deep-linking/ ·\n  https://v2.tauri.app/security/capabilities/\n- MDN, *Making PWAs installable*: what Chrome and Edge require of a manifest, and that Safari adds\n  any page to the Dock.\n  https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Making_PWAs_installable\n- Apple, *Use Safari web apps on Mac*. https://support.apple.com/en-us/104996\n\nSee also: [graph-visualization.md](graph-visualization.md) (the trial and the ruling on what draws\nthe graph) · [whose-tokens-pay-for-mapping.md](whose-tokens-pay-for-mapping.md) ·\n[single-player-utility.md](single-player-utility.md) § 6.5 (data ownership as a trust signal) ·\n[mobile-argument-ux.md](mobile-argument-ux.md) § 5.1 (the installable web app, for phones).\n"}