kSecureMessageRoutes
KSecureMessage HTTP API v1, see docs/prekey-publication.md and docs/server-authentication.md. The application must install ContentNegotiation with JSON. Routes only map HTTP to SecureMessageServer; authentication, validation, conflicts and atomicity live behind it.
Device recovery (docs/device-recovery.md), routine device authentication key rotation (docs/device-authentication-rotation.md) and last-device recovery (docs/last-device-recovery.md) carry their own two signatures in the body and no authentication headers. Registering the last-device recovery key is ServerAuth-signed; issuing a last-device recovery challenge is public. The delayed recovery key reset (docs/recovery-key-reset.md) is ServerAuth-signed on its device routes; its two user-scoped routes (/v1/users/{user}/…, status query and cancellation) carry the current recovery key's signature in the body instead, for a holder of the offline key without a working device.
Registration, prekey publication, message submission and mailbox drain are authenticated by the device: the signature covers the exact body bytes, so those routes read the raw body and authenticate it before parsing anything that is acted on. A request that fails authentication gets 401 and changes nothing. Registration additionally needs the host application's authorization (403 registration_not_authorized), and a submitted envelope's sender must be the authenticated device (403 sender_mismatch). Only prekey bundle fetch is public. Unexpected failures of the server or its storage get 500 with internal_error and no details. Request-supplied identifiers are logged only escaped (logSafe).
registrationContext is required: it gives the registration route the host's authentication context of the call (for example the principal the host's own authentication established), which server passes to its dev.kreienbuehl.ksecuremessage.server.DeviceRegistrationAuthorizer (S1.1, finding N1). The routes never read, log or return the context.