PINs & access

osd uses three separate PINs, each guarding a different door. This page is the single reference for what each PIN unlocks, who sets it and where, whether it has a default, and how it is rotated. It is written for both operators (Sanitäter at the tablet) and admins (who run the admin panel).

There is no username-and-password login at the tablet: the kiosk front door is a PIN. (The legacy operator login and the admin panel are the only places that still use email + password — see Admin panel.)

New here? Start with Onboarding for enrollment and first-use, then come back to this page when you need the PIN details.

The three PINs at a glance

PIN What it unlocks Who sets it & where Default Rotation

Shift-PIN

Connects a tablet to a specific Dienst at the front door ("Einsatzbereitschaft herstellen")

Admin, in the admin panel, when the Dienst is created (required)

None — the admin chooses 6 digits

Admin rotates it in the admin panel; operators cannot change it

Firmen-PIN (company)

Offline "Neuen Dienst anlegen" — creating a Dienst with no server and no Shift-PIN

Operator, at the front door or in Settings, on first use

None — set-on-first-use (no shipped default)

Anyone with the current Firmen-PIN, in Settings; the current PIN must be entered

Wartungs-/Admin-PIN (maintenance)

Access to Settings and the maintenance escape-hatch launcher

Operator/technician, on first use

None — set-on-first-use (no default)

In Settings; the old PIN is not re-verified today (see the warning below)

There is no factory-default PIN for any of the three. The occasionally-repeated “112112” Firmen-PIN default is a myth — it exists nowhere in the code. Every PIN is either chosen by the admin (Shift-PIN) or set on first use (Firmen-PIN, Wartungs-PIN).

How PINs are stored and protected

All three PINs share the same security machinery (src-tauri/src/commands/pin.rs):

  • Format: exactly 6 numeric digits. Anything shorter, longer, or non-numeric is rejected.

  • Storage: never stored as plaintext. Each PIN is hashed with argon2id (salt + parameters embedded in the PHC string) and the hash is kept in the device’s secrets.bin. The Shift-PIN’s authoritative hash lives server-side (see below) and syncs down.

  • Shared lockout / backoff: after 5 wrong attempts the PIN locks for 30 seconds. Each further wrong trip doubles the window (30 s → 60 s → 120 s …), capped at 15 minutes.

While a PIN is locked out, even the correct PIN is refused until the window expires. Wait out the timer rather than continuing to guess — every extra wrong attempt lengthens the next lock.

secrets.bin is not encrypted at rest. The security boundary is the OS application sandbox. A penetration test is still owed before public release — treat physical device access as the trust boundary.

Shift-PIN — connect a tablet to a Dienst

The Shift-PIN binds a tablet to one specific Dienst (event). It is entered at the front door under "Einsatzbereitschaft herstellen".

  • Set by the admin, in the admin panel, at Dienst creation — it is required to create a Dienst. (server/src/admin/events.rs)

  • The hash is stored server-side in Postgres (events.shift_pin_hash) and syncs down to enrolled devices. (src-tauri/src/commands/shift.rs)

  • Only Dienste in the active state are connectable — an inactive or ended Dienst will not accept its Shift-PIN.

  • Operators cannot change the Shift-PIN. The admin rotates it in the admin panel.

The front-door entry flow lives in src/views/EntryScreen.vue. For the full join sequence, see Dienst lifecycle; for where the admin sets and rotates the PIN, see Admin panel.

Firmen-PIN — create a Dienst offline

The Firmen-PIN (company PIN) gates the offline "Neuen Dienst anlegen" path — creating a Dienst locally when there is no server connection and therefore no Shift-PIN.

  • Set-on-first-use — no shipped default. The first time this door is used, the operator sets the Firmen-PIN. (src-tauri/src/commands/company.rs)

  • It can be set at the front door or later in Settings.

  • Rotation requires the current PIN: to change the Firmen-PIN you must enter the existing one. (src/components/settings/CompanyPinCard.vue)

Wartungs-/Admin-PIN — Settings and maintenance

The Wartungs-PIN (maintenance / admin PIN) gates two things: access to the app’s Settings, and the maintenance escape-hatch launcher described below.

  • Set-on-first-use — no default. The first entry into the maintenance dialog sets it. (src-tauri/src/commands/maintenance.rs, src/components/maintenance/MaintenancePinDialog.vue)

Known gap: rotating the Wartungs-PIN does not currently re-verify the old PIN. Anyone who can already reach the Settings dialog can change it without proving the current one. Until this is fixed, control of the maintenance overlay is the effective boundary.

The maintenance escape hatch

On a provisioned Device-Owner kiosk, osd locks the tablet into the app. The escape hatch is the sanctioned way to reach a small set of Android apps for maintenance without leaving the kiosk:

  1. Tap the Settings version label 10 times, quickly. (This works only on a provisioned Device-Owner tablet.)

  2. Enter the Wartungs-PIN.

  3. A time-boxed launcher (~300 seconds) opens with an allow-listed set of apps: Settings, Files, Camera, Notes, Maps, plus a bounded "enable USB debugging" verb for that window only.

  4. The launcher auto-relocks on exit, on timeout, or on reboot.

The trigger is 10 quick taps on the version label, not a long-press. The launcher window is bounded (~300 s) and USB debugging, if enabled, is enabled only for that window.

The escape hatch is implemented in src/views/Settings.vue and src/components/maintenance/MaintenanceLauncher.vue. For the full operator runbook — provisioning, recovery, updates, decommissioning — see Kiosk operations runbook.

What is not a PIN

  • The legacy operator login uses email + password, not a PIN.

  • The admin panel uses email + password, not a PIN.

Neither participates in the PIN lockout machinery described above.

See also