Two failures from the same root: an administrator cannot see the kiosk token, and a screen that was provisioned wrongly does not say so. The settings API masks every key whose name contains 'token', so the settings page shows '********'. The real value is visible for one moment - after Generate, before Save - and an administrator who copies the field at any other time provisions a screen with the literal mask. The kiosk then answers 404, exactly as it answers a caller it has never heard of, because the route deliberately does not advertise itself. Nothing anywhere says what went wrong. - Each kiosk gains a permission-gated provisioning-link route that returns the real setup URL, token included, to somebody who already holds settings.edit. The mask stays: a token has no business in an ordinary settings list. The copy step just stops depending on catching the one moment it is on screen. Revealing it writes an audit row, since that is when the value left the database. Both settings pages get a "Copy setup link" button, which falls back to showing the link when the clipboard is refused - it is, over plain http and in locked-down browsers. - The USB kiosk asks the server on load whether this screen may be used, and says plainly when it may not. It rendered a keypad and only failed once somebody had typed their SSO, which reads as broken rather than as not set up. It cannot guess: the enabled flag is public and only says the site has a kiosk, and a caller admitted by network holds no token to look for, so the parts kiosk's localStorage check would warn exactly the callers the allowlist exists to serve. The probe is a badge-less session request - the gate runs before any badge handling, so refused is 404 and admitted is the validation error, with no lookup and nothing recorded. A test pins that ordering, because reordering it would start telling admitted screens they are not set up. Verified in a browser, not only in tests: provisioning with the mask lands on the refused screen, a correct token gets the drive list and survives a plain revisit, and a tokenless caller inside the allowlist gets straight in.
47 KiB
47 KiB