Ya documentamos el recetario especial y el libro de estupefacientes (arts. 241 y 242 de la Ley General de Salud) y la cédula que no llega al PDF de la receta (art. 29 del RIS). Este hallazgo es distinto de los dos: no es sobre cómo se documenta la receta ni sobre qué imprime, es sobre quién puede emitirla. Verificamos en el código de FaunaWare que el sistema deja recetar morfina -un estupefaciente, listado por su nombre en la propia Ley General de Salud- a cualquier usuario con el rol "doctor", sin comprobar en ningún punto que esa persona tenga una cédula profesional registrada, ni siquiera que exista una ficha de médico vinculada a su cuenta.
La ley no autoriza por rol de sistema: autoriza por título registrado
El artículo 240 de la Ley General de Salud es explícito sobre quién puede prescribir estupefacientes, y bajo qué condición:
"Sólo podrán prescribir estupefacientes los profesionales que a continuación se mencionan, siempre que tengan título registrado por las autoridades educativas competentes [...]: I. Los médicos cirujanos; II. Los médicos veterinarios, cuando los prescriban para la aplicación en animales, y III. Los cirujanos dentistas, para casos odontológicos."
La condición no es un detalle administrativo: es la que abre el artículo, antes incluso de nombrar a los tres tipos de profesional. Y el artículo 28 Bis de la misma ley, que regula quién puede prescribir medicamentos en general -no sólo estupefacientes-, repite el requisito para los médicos veterinarios en los mismos términos: "deberán contar con cédula profesional expedida por las autoridades educativas competentes". La morfina, la sustancia con la que el propio test de la plataforma verifica este flujo, está nombrada explícitamente entre los estupefacientes del artículo 239 de la ley.
La sanción: el mismo artículo 421 que ya mide el libro de estupefacientes
El catálogo de infracciones de la Ley General de Salud nombra el artículo 240 de forma expresa -no cae en un residual, como sí ocurre con el consentimiento informado de otros SaaS de esta misma serie-. El artículo 421 lista al 240 junto al 242 (el libro de contabilidad) entre las violaciones que sanciona:
"Se sancionará con una multa equivalente de seis mil hasta doce mil veces el salario mínimo general diario vigente en la zona económica de que se trate, la violación de las disposiciones contenidas en los artículos [...] 240, 242, [...] de esta Ley."
Con el salario mínimo general diario vigente en 2026 ($315.04 en la zona general del país, $440.87 en la Zona Libre de la Frontera Norte), el rango de esa multa es de $1,890,240.00 a $3,780,480.00 MXN en zona general, y de $2,645,220.00 a $5,290,440.00 MXN en la frontera norte. El artículo 423 duplica el monto en caso de reincidencia dentro de un año. El monto exacto dentro del rango lo determina la autoridad sanitaria caso por caso, conforme a los criterios del artículo 418.
| Elemento | Qué dice la norma |
|---|---|
| Quién puede prescribir estupefacientes, y bajo qué condición | Art. 240, LGS: título registrado; fracción II nombra a los médicos veterinarios |
| Cédula profesional exigida a quien prescribe medicamentos en general | Art. 28 Bis, LGS |
| La morfina es un estupefaciente nombrado por la ley | Art. 239, LGS |
| Infracción al art. 240 | Sancionada de forma expresa por el art. 421, LGS (no cae en un residual) |
| Multa | Art. 421, LGS: 6,000 a 12,000 veces el salario mínimo general diario ($1,890,240.00-$3,780,480.00 MXN zona general; $2,645,220.00-$5,290,440.00 MXN ZLFN, 2026) |
| Reincidencia | Art. 423, LGS: duplica el monto dentro de un año |
Verificado en el código: el rol abre la puerta, nadie pregunta por la cédula
Confirmamos el hallazgo directamente en el código de FaunaWare (repo medware-vet, rama main). El endpoint que emite la receta exige el rol doctor y el permiso encounters:write -nada más- en PrescriptionsController.issue() (services/clinical/src/prescriptions/prescriptions.controller.ts:39-47). Ese rol es una etiqueta de acceso al sistema, asignable por un clinic-admin desde el módulo de usuarios: no implica que la cuenta tenga una ficha de médico vinculada, y mucho menos que esa ficha tenga cédula profesional capturada.
Quien identifica al emisor de la receta es la función medicoDelEmisor() (services/clinical/src/common/medico-del-emisor.ts:55-85): busca en la tabla doctors por el correo de quien hace la petición, y trae únicamente id y full_name -nunca professional_license-. Si no encuentra ninguna coincidencia, devuelve { id: null, fullName: null } (línea 53, 78) sin lanzar ningún error. El servicio que emite la receta, PrescriptionsService.issue() (services/clinical/src/prescriptions/prescriptions.service.ts:70-114), usa ese resultado tal cual: inserta la receta con doctor_id en null si no hubo coincidencia (línea 94, 105), y con auth.username como respaldo del nombre (línea 95). En ningún punto de esa función -ni en ninguna otra que participe del flujo- se lee o se exige professional_license.
La única validación real que existe en issue() es distinta: si algún medicamento es controlado de grupo I, II o III (líneas 75-84), exige capturar un specialFolio -de lo contrario responde 400-. Es una validación de formato, no de identidad: el campo acepta cualquier texto no vacío, sin comprobar que corresponda a un recetario autorizado ni que quien lo captura tenga cédula. La migración que crea la tabla doctors confirma que professional_license text es una columna sin NOT NULL (packages/db/migrations/1700000062000_doctor_profile.cjs:23): la base de datos tampoco lo exige.
El propio test de la plataforma lo prueba con morfina
El test e2e de FaunaWare confirma el hallazgo con el caso más sensible posible. En tests/e2e/stack.e2e.mjs:332-341 se crea el usuario doc@e2e.mx con role: 'doctor' -sin ninguna ficha en la tabla doctors, sin cédula-. Más adelante, en tests/e2e/stack.e2e.mjs:3254-3272, ese mismo usuario intenta recetar { drug: 'Morfina 10 mg', controlled: true, controlledGroup: 'I' }: sin specialFolio recibe 400 (línea 3261) -la validación de formato sí actúa-, pero con specialFolio: 'REC-CTRL-0001' -un texto arbitrario, no verificado contra ningún recetario real- recibe HTTP 201 (línea 3271) y la receta se persiste. El propio test documenta, sin proponérselo, que basta el rol y un folio de texto libre para recetar un estupefaciente.
Qué significa en la práctica, y qué falta en el producto
Un clinic-admin puede dar de alta a cualquier persona con el rol "doctor" -un asistente, un pasante, alguien en capacitación- y esa cuenta queda habilitada para recetar morfina el mismo día, sin que el sistema pida en ningún punto una cédula profesional ni una ficha de médico vinculada. Lo que falta no es el campo: professional_license ya existe en la tabla doctors desde 2026 (documentado en la pieza sobre la cédula ausente en el PDF). Lo que falta es que issue() lo consulte antes de aceptar una receta de estupefacientes: rechazar cuando medicoDelEmisor() devuelve id: null, o cuando el médico encontrado no tiene professional_license capturada. Puedes ver ese recorrido completo, del rol a la receta emitida, en del rol a la receta: el flujo completo en FaunaWare, o estimar la exposición con tus propios números en la calculadora de exposición por receta de estupefacientes sin acreditación profesional.
Preguntas frecuentes
¿Esto es lo mismo que la cédula que no aparece en el PDF de la receta?
No. Aquella pieza trata de un documento que se genera con datos incompletos -el veterinario existe, tiene cédula capturada, pero el PDF no la imprime-. Ésta trata de que el sistema nunca comprueba que exista un veterinario acreditado detrás de la cuenta que factura la receta.
¿El folio especial (specialFolio) no resuelve esto?
No: es una validación de formato -que el campo no esté vacío cuando el medicamento es controlado-, no una validación de identidad. Un texto arbitrario como "REC-CTRL-0001" pasa la validación igual que un folio real emitido por la autoridad.
¿Significa que mi clínica ya tiene recetas emitidas sin veterinario acreditado?
No necesariamente: el hallazgo es que el sistema lo permite y no lo detecta, no que ya haya ocurrido. Si en tu clínica sólo das el rol "doctor" a veterinarios con cédula vigente, hoy no tienes el problema -pero tampoco hay ninguna alerta si algún día se lo das a alguien más.
¿Cuál es la multa exacta?
La Ley General de Salud no fija un monto único: de 6,000 a 12,000 veces el salario mínimo general diario vigente en la zona económica (de $1,890,240.00 a $3,780,480.00 MXN en zona general, de $2,645,220.00 a $5,290,440.00 MXN en la Zona Libre de la Frontera Norte, con el salario mínimo 2026), calificada por la autoridad sanitaria según los cinco criterios del artículo 418 -no es un cobro automático por cada caso-.
Fuentes consultadas: Ley General de Salud, texto vigente publicado por la Cámara de Diputados del H. Congreso de la Unión (últimas reformas DOF 15-01-2026), artículos 28 Bis, 239, 240, 418, 421 y 423. Salario mínimo general diario vigente en 2026 por zona económica (Comisión Nacional de los Salarios Mínimos). Este artículo es orientativo y no sustituye una revisión de tu caso por tu responsable sanitario o asesor legal.
Ve cómo FaunaWare autoriza hoy una receta de controlados, y dónde falta el candado
Te mostramos en vivo el alta de un usuario con rol "doctor", la emisión de una receta de controlados, y el punto exacto donde nadie pregunta por la cédula.
Agenda una demo gratis