From f6658bd092f6a6e3eeb4b42d9839bed5fa4df5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Tue, 18 Aug 2026 03:01:09 +0000 Subject: [PATCH] docs: kiosk replaces the marketplace, and the shape it takes --- docs/kiosk-ecosystem.md | 89 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/kiosk-ecosystem.md diff --git a/docs/kiosk-ecosystem.md b/docs/kiosk-ecosystem.md new file mode 100644 index 00000000..0fff7d7c --- /dev/null +++ b/docs/kiosk-ecosystem.md @@ -0,0 +1,89 @@ +# Kiosk — the store, and what it replaces + +Decided in conversation on 2026-08-18. Direction, not a work order: none of it is built, and the parts that +touch third parties are months out. Recorded so the shape is not re-argued. + +The commercial reasoning is `BUSINESS-MODEL.md` in the `officer-oas` repository; this file is the technical +half. + +--- + +## One brand, two halves + +**Kiosk** is what a person sees. `kiosk.officer.dev` is the public hub: a searchable catalogue of +everything in the Officer ecosystem — plugins, apps, the plugins that have companion apps, the apps that +have plugins. **Nothing happens there.** It stores metadata and exposes an API, so a platform can embed it. + +Underneath, two separate plugins with separate repositories: + +| | ships to | holds | is | +| ------------------- | -------------------------- | ------------------------------------------------- | ------------------- | +| the **storefront** | every instance | no database, no sidecar | free infrastructure | +| the **apps engine** | whoever distributes builds | 4 tables, a sidecar, artefacts, Apple credentials | the paid product | + +They are split on that last column rather than on any technical boundary. Bundled, every server would carry +app-distribution machinery it will never run, and the commercial half would live inside the plugin that can +never be uninstalled. That is the wrong seam. + +**Brand is not `appName`.** `label` is what a person reads; `appName` is the directory name and the route. +Both can be "Kiosk" to a human while being distinct identifiers underneath — the same way `email`'s label is +"Email". + +--- + +## `/marketplace` goes away + +Replaced by `/kiosk`, and the screen moves out of the platform into the storefront plugin, which mounts +exactly the way every other plugin does. + +**The install machinery does NOT move.** `src/servers/plugins/` — discover, mount, install, schema, +ecosystem — is how any plugin gets mounted, including Kiosk itself, so it cannot live inside one. It is +already API-shaped (`/api/plugins`: what is on this machine, what is installed, and the four verbs that +change it), which is what makes this a UI move rather than a refactor. + +So: **the platform keeps the mechanism, the plugin owns the shop window.** + +Because a first-party plugin mounts at `/` (`mountPrefix`, verified), the storefront must be +`appName: 'kiosk'`. That settles the identifier by way of the route. + +## The storefront is a privileged plugin + +Not a normal one, and the differences are deliberate: + +- **installed on every instance**, as a setup step rather than a marketplace action — you cannot install the + installer with the installer; +- **not listed** among installed plugins; +- **no uninstall UI**; +- **and removing it must not brick the server.** A user can always stop or delete the PM2 service by hand, + so the platform has to survive the storefront being absent. The install verbs are the platform's and stay + reachable without it; that is what makes this true rather than hoped. + +## Two calls to action, one catalogue + +The hub is a discovery surface for people who do not have a server yet — someone browses it and asks their +admin for something. That is a funnel, and it means the two halves end differently: + +- **a plugin can be installed** — by an admin, on a server, now; +- **an app cannot be installed from the hub at all.** It needs a server running the apps plugin, an account, + a registered device, and somebody paying Apple. + +Same catalogue, two endings. Worth designing the entry shape around, rather than discovering it when the +Install button does nothing for half the listings. + +**The pairing is declared data, not inference.** "Plugins that have apps" cannot be derived from names that +happen to match; a manifest field declares the companion. It is the smallest piece of work here and the +whole browsing experience hangs off it. Safe to put in the public catalogue — names, not artefacts. + +--- + +## Open + +- **What the apps plugin is called.** It cannot be `kiosk`, since the storefront takes that with the route. + `kiosk-apps` is legible and obviously paired; `builds` describes what it manages. Currently sitting at + `plugins/kiosk` (and `gitea.officer.dev/plugins/kiosk`) from the night it was started — **that name is + wrong and pending a decision**, which is cheap now and expensive after either ships. +- **Whether `marketplace.officer.dev` becomes `kiosk.officer.dev`.** Precedent says rename the screen and + leave the machine endpoint alone: every installed server has the current URL baked in as its default, so a + rename drops them to the bundled catalogue until they update. +- Everything about third parties — review, pinning, confining a plugin's sidecar. See `TODO.md`, + "Plugin ecosystem — before it opens to third parties". Months away and not a prerequisite for the rename.