Vai al contenuto
Spedizione in 24/48h in tutta Italia
Vai al contenuto
Navigazione documentazione

Questa pagina non è ancora disponibile nella lingua scelta. È mostrata la versione EN.

Kiosk Mode

Kiosk mode is a simplified backoffice at /kiosk, for people who need to keep a website and their own account running without learning the full administration interface.

It is an alternative view of k0smos, not a second application: every action it offers is performed by the same code the full backoffice uses, and every page requires the same permission the equivalent /admin page requires. Kiosk mode can only ever show less than the backoffice — never more.

The surface is part of core, so it exists on every tenant. What decides whether anyone can see it is the ACL, not a module switch: granting the gate permission always produces a working page, and revoking it always closes the surface.

What an operator sees

Page What it does Requires
/kiosk The list of features this operator may use kiosk.use
/kiosk/account Display name, language, light/dark and colours, password confirmation and two-factor authentication kiosk.use
/kiosk/site Public company details and the width of the public pages kiosk.use + system.read, settings.company or settings.front_content

The home page also shows cards for Pages, Blog, Information pages and Media when the tenant has those modules active and the operator holds their permission. Those cards are marked as opening the full backoffice, because that is where the editors live.

The kiosk surface has no entries for: users and roles, module activation, system settings, connectors and imports, queues, storage administration, MCP and agent configuration.

Setting up an operator

  1. Open /admin/roles and create a role from the Kiosk operator preset. It grants kiosk.use plus the minimum website permissions.
  2. Assign that role to the person in /admin/users/{id}.
  3. The Kiosk mode entry appears in their sidebar under Tools, and /kiosk opens for them.

The preset intentionally leaves out system.write, because that single permission unlocks every system settings page in k0smos. It grants two narrow alternatives instead:

  • settings.company — read and save the public company details.
  • settings.front_content — read and save the width of the public pages.

Each /kiosk/site panel is writable only for the operator who holds its code, so someone with just settings.company saves the company panel and reads the width panel. Both codes also work on the underlying endpoints, so nothing fails on save. system.write still opens everything and remains the administrator's tool; you should not need to hand it to an operator any more.

The preset also grants blog.delete and media.delete — the content an operator routinely publishes and withdraws — but withholds page.delete and info.delete: pages are structural and information pages carry the legal copy, so removing one breaks navigation or compliance rather than tidying a mistake.

Password changes may require a code from email or an authenticator. The account page asks for that code before confirming the change and also offers the existing two-factor enrollment/reset controls. Company saves preserve settings not shown in the kiosk panel. Company and page-width saves record the operator and changed field names in the audit log without recording their values.

What the gate does and does not do

kiosk.use opens the shell. It is never a substitute for the permission behind a page: /kiosk/site still demands one of the settings codes, and a card still demands the permission of the page it links to. An operator holding only kiosk.use sees the shell and their own account, and nothing else.

Conversely, holding a website permission without kiosk.use does not open /kiosk at all. The two are required together.

By default kiosk mode confines nobody: an operator who also holds administration permissions still reaches /admin normally, and the kiosk shell links there. Kiosk is a simpler way in, not a lock — unless you ask for one.

Editing content and saving settings

Page, information-page and blog editors show the actions allowed for the current operator. Creating or duplicating pages and deleting information pages remain outside the kiosk preset. Blog deletion has its own blog.delete permission; editing an article alone does not allow deletion. When updating an existing installation, apply the Blog migrations and explicitly grant this permission to existing custom roles that should delete articles. The migration preserves all existing custom grants and labels.

Website saves confirm success only after a valid response. Switching to fluid layout preserves the last saved fixed width. Password confirmation returns keyboard focus to the password action after completion. If JavaScript is disabled or cannot load, the page explains that saving is unavailable and keeps the save buttons disabled; navigation and saved values remain available.

Locking an operator inside kiosk mode

Edit the role and tick Keep inside kiosk mode. Someone whose roles are all confined then stays inside the surface: any other backoffice address sends them back to /kiosk, and the shell stops offering the link to the full backoffice. Use it for workstations that get handed between people. The role must have kiosk.use before confinement can be enabled; disable confinement before removing that permission. Confined logins open /kiosk directly.

Four things are worth knowing before you tick it:

  • It removes no permission. The role keeps everything it holds; only where its holders may navigate changes. Untick it and they are back to normal immediately.
  • It is unanimous. Someone who also holds one ordinary role keeps full access, so adding a role can never lock a person out by surprise.
  • It never strands anyone. The pages their own kiosk cards link to stay open, along with their declared supporting editor operations. Public pages and media remain available for preview; unrelated account APIs stay closed.
  • Confined logins get no "remember me". On a shared machine a long-lived session would hand the account to whoever sits down next, so the box is ignored for them.

System roles cannot be confined — confining the administrator role would lock everyone out of the backoffice with no way back in — so the option does not appear on them.

For developers: extending the surface

A module adds an entry by implementing KioskCapabilityProviderModuleInterface and declaring a route name, never a URL. The declaration is accepted only when all four of these hold:

  1. the route is registered — so a card whose module is inactive disappears;
  2. the route is a static GET page below /admin or /kiosk, without URL/host parameters or a link to the whole backoffice root;
  3. the route really enforces every permission the declaration names — so a card cannot be advertised as cheaper than the page behind it, cannot widen its audience past the route's own condition, and a route that enforces nothing can never appear;
  4. the module has not already contributed five entries.

Card visibility also checks every required route permission, its alternatives and policy vetoes. Supporting editor APIs are listed explicitly in operationRouteNames and must be registered and permission-guarded. Scoped API tokens retain the user's confinement independently of their permission scope.

A contribution is therefore a link to a page the operator could already open from /admin. It cannot escalate privileges, cannot render inside the kiosk shell, and cannot displace a core page by reusing its id; a rejected declaration is dropped rather than repaired, and logged at warning level so a missing card is never silent.

Verification and deployment

The development review is complete. The retained checks passed 93 PHP tests (706 assertions), 19 JavaScript tests and 36 Chromium scenarios across Default and Sober. The browser suite includes 320/1440 px rendering, real company/width saves, email/TOTP confirmation and retry, synchronous code-input focus, dark focus, long identities, tooltips and disabled/missing JavaScript. Syntax, focused static analysis and documentation validation also pass.

To repeat the browser checks from the repository root:

node tools/benchmarks/kiosk-smoke.mjs reports/kiosk-smoke

Use Node 22 or newer, PHP and installed Chromium. Set K0SMOS_PHP_BINARY or K0SMOS_CHROME_BINARY when their executable paths differ. Existing Default and Sober build assets must be present; the runner never builds themes. Its loopback servers, random tenant descriptors and temporary SQLite database are created and removed automatically, including on failure. It accepts no runtime tenant or target URL. Assertions, screenshots and server logs remain in the output directory. An unsuccessful check exits nonzero.

Browser accessibility-tree checks verify labels, descriptions, live-region semantics and focus; they do not establish what a real screen reader speaks. No real screen reader was available for this review. During deployment, check the selected browser, screen reader, palette and actual workstation: navigate with Tab/Shift+Tab, complete password verification, hear the error/success announcements and confirm that focus returns to the password action. Treat any failure there as a concrete compatibility issue.

Apply the Blog permission migration as part of normal deployment and review explicit deletion grants on existing custom roles. Runtime tenant migrations, asset builds and activation were not performed by the development checks.

What kiosk mode is not

Kiosk mode is not digital signage. There is no unattended display, no paired device, no scheduled playlist and nothing public. That is a separate product question, still unanswered, recorded in ADR 0009.

The architecture, invariants and test coverage are in the complete reference § 30.