Two component-id collisions, both from the same cause: two paths that
are two doors onto one action, documented independently.
DELETE /api/devices/{id} and DELETE /api/auth/me/devices/{id} both call
revokeDeviceCascade and answer with the same shape. Each grew its own
DeviceRevokeResponse, which the emitter refuses outright. The response
moves to shared.ts so neither module owns it and the next door onto the
same call finds it; the two envelopes keep separate names because an
envelope names an operation.
The settings module took both halves by hand rather than by keep-both:
one side added nine paths, the other three, with no overlap but a shared
import block and a shared reminder-thresholds entry that a mechanical
union duplicated.