Summary
A deployment-level configuration for the web container and embeds that pins what the app is allowed to do — a read-only kiosk mode and everything between it and the full app — enforced by the server that serves the build, not only by the UI.
Why
The web container has exactly one access control today: docker/entrypoint.sh optionally turns on HTTP Basic Auth with a single shared credential over the app and /sidecar. It is all-or-nothing. Once someone is past that password (or if there is no password, which is the default), they have the entire app.
There is no way to express the deployments people actually stand up:
- a public kiosk or exhibit terminal: pan, zoom, identify, nothing else;
- a classroom or workshop instance: the full map and processing tools, but no plugin installs and no arbitrary remote URLs;
- an embedded map on a public site where the surrounding page should not become a general-purpose data-fetching proxy;
- an internal instance where local filesystem access and export must be off because the container can see mounted data the viewer should not walk out with.
GEOLIBRE_CONVERSION_ROOTS already confines the sidecar's filesystem reach, which shows the shape works — it just stops at conversion.
Proposal
1. A capability manifest served with the build
A JSON document the container serves (and the desktop build can optionally load), listing the privileges granted for this deployment, using the vocabulary from the capability-model issue. Generated from environment variables in entrypoint.sh, in keeping with how the container is already configured:
GEOLIBRE_MODE=kiosk|classroom|full # a named preset
GEOLIBRE_DENY=plugins:install,export:data # subtract from the preset
GEOLIBRE_ALLOW=processing:run # add back
2. Presets worth shipping
- kiosk — open the configured project; pan, zoom, layer toggles, identify. No add-data, no editing, no export, no settings, no plugin install.
- classroom — the full app minus
plugins:install, connections:manage, and settings:manage.
- full — today's behavior, and the default, so no existing deployment changes.
3. Enforcement at the serving layer, not just the client
The manifest tells the UI what to disable, but nginx must also refuse the corresponding requests: no /sidecar processing routes in kiosk mode, no /ai proxy where the assistant is denied. A client-side-only kiosk mode is a suggestion that anyone with devtools declines.
4. The embed case
packages/embed and the URL parameters already have the right instinct — the embed API is off by default with an origin allowlist. Extend that to the capability set, so an embed host can be granted a narrow, explicit slice rather than the current on/off. Keep this aligned with #1525 rather than adding a second embed configuration mechanism.
Scope notes
- Depends on the capability model for its vocabulary; without it this becomes another pile of ad-hoc flags.
full must stay the default. Existing containers must behave identically after this lands.
- Document that Basic Auth remains a single shared credential and is not per-user accounts — the current docs are already honest about this, and adding modes should not blur it.
Effort
Medium once the capability model exists.
Part of #1665 (access control umbrella).
Summary
A deployment-level configuration for the web container and embeds that pins what the app is allowed to do — a read-only kiosk mode and everything between it and the full app — enforced by the server that serves the build, not only by the UI.
Why
The web container has exactly one access control today:
docker/entrypoint.shoptionally turns on HTTP Basic Auth with a single shared credential over the app and/sidecar. It is all-or-nothing. Once someone is past that password (or if there is no password, which is the default), they have the entire app.There is no way to express the deployments people actually stand up:
GEOLIBRE_CONVERSION_ROOTSalready confines the sidecar's filesystem reach, which shows the shape works — it just stops at conversion.Proposal
1. A capability manifest served with the build
A JSON document the container serves (and the desktop build can optionally load), listing the privileges granted for this deployment, using the vocabulary from the capability-model issue. Generated from environment variables in
entrypoint.sh, in keeping with how the container is already configured:2. Presets worth shipping
plugins:install,connections:manage, andsettings:manage.3. Enforcement at the serving layer, not just the client
The manifest tells the UI what to disable, but nginx must also refuse the corresponding requests: no
/sidecarprocessing routes in kiosk mode, no/aiproxy where the assistant is denied. A client-side-only kiosk mode is a suggestion that anyone with devtools declines.4. The embed case
packages/embedand the URL parameters already have the right instinct — the embed API is off by default with an origin allowlist. Extend that to the capability set, so an embed host can be granted a narrow, explicit slice rather than the current on/off. Keep this aligned with #1525 rather than adding a second embed configuration mechanism.Scope notes
fullmust stay the default. Existing containers must behave identically after this lands.Effort
Medium once the capability model exists.
Part of #1665 (access control umbrella).